[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: NFS expert, please diagnose this



Hello.


I think I see the problem with regard to setuid programs and nfs.
It's in the kernel.

It's in the file kernel-source-2.0.27/fs/nfs/proc.c.
Alas the same code is repeated in several places, so I'm not sure how to
fix it: there must be a reason for exact this coding.

Does anybody here know what to do? Or know whom I might contact to get a
second opinion?


Thanks,

							MartinS


Here follows a snippet from the above mentioned file and an possible scenario
(the one that makes at fail if /var/spool/cron/atjobs is on a nfs mounted
partition) to illustrate the problem:
---- Start of proc.c snippet. ----
[...]
int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
ame,
                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
        int *p, *p0;
        int status;
        int ruid = 0;

        PRINTK("NFS call  lookup %s\n", name);
#ifdef NFS_PROC_DEBUG
        if (!strcmp(name, "xyzzy"))
                proc_debug = 1 - proc_debug;
#endif
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
                return -EIO;
retry:
        p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
                status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fhandle(p, fhandle);
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply lookup\n");
                /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
                        ruid = 1;
                        goto retry;
                }
                PRINTK("NFS reply lookup failed = %d\n", status);
                status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
        return status;
}

[...]

static int *nfs_rpc_header(int *p, int procedure, int ruid)
{
        return rpc_header(p, procedure, NFS_PROGRAM, NFS_VERSION,
                        (ruid ? current->uid : current->fsuid),
                        current->egid, current->groups);
}

[...]
---- End of proc.c snippet. ----

Now first ruid is initialised to 0. First time around we fail looking up the
file and status (what is supposed to be propagated to errno) is set to 2
(ENOENT), so the statements "ruid = 1;" and "goto retry;" is executed.

Second time around the lookup will be performed as current->uid, which
obviously fail (as the directory is only writeable for root), hence
status (and after that errno) is set to 13 (EACCES).

Comments?


--
TO UNSUBSCRIBE FROM THIS MAILING LIST: e-mail the word "unsubscribe" to
debian-user-request@lists.debian.org . 
Trouble?  e-mail to templin@bucknell.edu .


Reply to: