diff -ru a/fs/nfs/dir.c b/fs/nfs/dir.c --- a/fs/nfs/dir.c 2005-02-06 18:05:03.000000000 +0100 +++ b/fs/nfs/dir.c 2005-02-14 22:41:49.000000000 +0100 @@ -580,6 +580,7 @@ struct nfs_fattr fattr; unsigned long verifier; int isopen = 0; + struct rpc_groups fsg; parent = dget_parent(dentry); lock_kernel(); @@ -615,7 +616,9 @@ goto out_bad; verifier = nfs_save_change_attribute(dir); - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); + fsg.ngroups = 1; + fsg.groups[0] = dir->i_gid; + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, &fsg); if (error) goto out_bad; if (nfs_compare_fh(NFS_FH(inode), &fhandle)) @@ -709,6 +712,7 @@ int error; struct nfs_fh fhandle; struct nfs_fattr fattr; + struct rpc_groups fsg; dfprintk(VFS, "NFS: lookup(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); @@ -728,7 +732,9 @@ if (nfs_is_exclusive_create(dir, nd)) goto no_entry; - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); + fsg.ngroups = 1; + fsg.groups[0] = dir->i_gid; + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, &fsg); if (error == -ENOENT) goto no_entry; if (error < 0) { @@ -939,7 +945,7 @@ * Code common to create, mkdir, and mknod. */ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct inode *inode; int error = -EACCES; @@ -949,7 +955,7 @@ return 0; if (fhandle->size == 0) { struct inode *dir = dentry->d_parent->d_inode; - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, fsg); if (error) goto out_err; } @@ -985,6 +991,7 @@ struct inode *inode; int error; int open_flags = 0; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); @@ -997,7 +1004,7 @@ lock_kernel(); nfs_begin_data_update(dir); - inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); + inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, &fsg); nfs_end_data_update(dir); if (!IS_ERR(inode)) { d_instantiate(dentry, inode); @@ -1022,6 +1029,7 @@ struct nfs_fattr fattr; struct nfs_fh fhandle; int error; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); @@ -1035,10 +1043,10 @@ lock_kernel(); nfs_begin_data_update(dir); error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev, - &fhandle, &fattr); + &fhandle, &fattr, &fsg); nfs_end_data_update(dir); if (!error) - error = nfs_instantiate(dentry, &fhandle, &fattr); + error = nfs_instantiate(dentry, &fhandle, &fattr, &fsg); else d_drop(dentry); unlock_kernel(); @@ -1054,6 +1062,7 @@ struct nfs_fattr fattr; struct nfs_fh fhandle; int error; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); @@ -1073,10 +1082,10 @@ #endif nfs_begin_data_update(dir); error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle, - &fattr); + &fattr, &fsg); nfs_end_data_update(dir); if (!error) - error = nfs_instantiate(dentry, &fhandle, &fattr); + error = nfs_instantiate(dentry, &fhandle, &fattr, &fsg); else d_drop(dentry); unlock_kernel(); @@ -1086,13 +1095,14 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) { int error; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: rmdir(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); lock_kernel(); nfs_begin_data_update(dir); - error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); + error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name, &fsg); /* Ensure the VFS deletes this inode */ if (error == 0 && dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0; @@ -1112,6 +1122,7 @@ struct qstr qsilly; struct dentry *sdentry; int error = -EIO; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, @@ -1158,11 +1169,11 @@ if (dentry->d_inode) { nfs_begin_data_update(dentry->d_inode); error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, - dir, &qsilly); + dir, &qsilly, &fsg); nfs_end_data_update(dentry->d_inode); } else error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, - dir, &qsilly); + dir, &qsilly, &fsg); nfs_end_data_update(dir); if (!error) { nfs_renew_times(dentry); @@ -1187,6 +1198,7 @@ { struct inode *dir = dentry->d_parent->d_inode; struct inode *inode = dentry->d_inode; + struct rpc_groups fsg = { 1, { dir->i_gid } }; int error = -EBUSY; dfprintk(VFS, "NFS: safe_remove(%s/%s)\n", @@ -1201,13 +1213,13 @@ nfs_begin_data_update(dir); if (inode != NULL) { nfs_begin_data_update(inode); - error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); + error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, &fsg); /* The VFS may want to delete this inode */ if (error == 0) inode->i_nlink--; nfs_end_data_update(inode); } else - error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); + error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, &fsg); nfs_end_data_update(dir); out: return error; @@ -1260,6 +1272,7 @@ struct nfs_fh sym_fh; struct qstr qsymname; int error; + struct rpc_groups fsg = { 1, { dir->i_gid } }; dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name, symname); @@ -1282,10 +1295,10 @@ lock_kernel(); nfs_begin_data_update(dir); error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, - &attr, &sym_fh, &sym_attr); + &attr, &sym_fh, &sym_attr, &fsg); nfs_end_data_update(dir); if (!error) { - error = nfs_instantiate(dentry, &sym_fh, &sym_attr); + error = nfs_instantiate(dentry, &sym_fh, &sym_attr, &fsg); } else { if (error == -EEXIST) printk("nfs_proc_symlink: %s/%s already exists??\n", @@ -1300,6 +1313,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; + struct rpc_groups fsg = { 1, { dir->i_gid } }; int error; dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n", @@ -1316,7 +1330,7 @@ nfs_begin_data_update(dir); nfs_begin_data_update(inode); - error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); + error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name, &fsg); nfs_end_data_update(inode); nfs_end_data_update(dir); unlock_kernel(); @@ -1353,6 +1367,14 @@ struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct dentry *dentry = NULL, *rehash = NULL; + struct rpc_groups fsg = { + .ngroups = 3, + .groups = { + old_dir->i_gid, + new_dir->i_gid, /* old_dir != new_dir */ + old_inode->i_gid /* reparent a dir */ + } + }; int error = -EBUSY; /* @@ -1425,7 +1447,7 @@ nfs_begin_data_update(new_dir); nfs_begin_data_update(old_inode); error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name); + new_dir, &new_dentry->d_name, &fsg); nfs_end_data_update(old_inode); nfs_end_data_update(new_dir); nfs_end_data_update(old_dir); @@ -1486,6 +1508,8 @@ cache.cred = cred; cache.jiffies = jiffies; status = NFS_PROTO(inode)->access(inode, &cache); + dfprintk(VFS, "NFS: access()=%d for ino %lu, cred %p, mask 0x%x->0x%x\n", + status, inode->i_ino, cred, mask, cache.mask); if (status != 0) return status; nfs_access_add_cache(inode, &cache); @@ -1499,6 +1523,7 @@ { struct rpc_cred *cred; int res; + struct rpc_groups fsg = { 1, { inode->i_gid } }; if (mask == 0) return 0; @@ -1518,7 +1543,7 @@ if (!NFS_PROTO(inode)->access) goto out_notsup; - cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, &fsg, 0); res = nfs_do_access(inode, cred, mask); put_rpccred(cred); unlock_kernel(); diff -ru a/fs/nfs/file.c b/fs/nfs/file.c --- a/fs/nfs/file.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/file.c 2005-02-14 21:38:12.000000000 +0100 @@ -95,7 +95,6 @@ return res; lock_kernel(); - /* Do NFSv4 open() call */ if ((open = server->rpc_ops->file_open) != NULL) res = open(inode, filp); unlock_kernel(); diff -ru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/inode.c 2005-02-14 22:41:49.000000000 +0100 @@ -366,7 +366,10 @@ clnt->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; - clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0; + if (server->flags & NFS_MOUNT_BROKEN_SUID) { + printk(KERN_WARNING "NFS: mount option \"broken_suid\" ignored.\n"); + server->flags &= ~NFS_MOUNT_BROKEN_SUID; + } clnt->cl_chatty = 1; return clnt; @@ -538,7 +541,6 @@ { NFS_MOUNT_NOCTO, ",nocto", "" }, { NFS_MOUNT_NOAC, ",noac", "" }, { NFS_MOUNT_NONLM, ",nolock", ",lock" }, - { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" }, { 0, NULL, NULL } }; struct proc_nfs_info *nfs_infop; @@ -743,6 +745,7 @@ { struct inode *inode = dentry->d_inode; struct nfs_fattr fattr; + struct rpc_groups fsg; int error; if (attr->ia_valid & ATTR_SIZE) { @@ -763,7 +766,11 @@ filemap_fdatawait(inode->i_mapping); nfs_wb_all(inode); } - error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); + fsg.ngroups = 0; + fsg.groups[fsg.ngroups++] = inode->i_gid; /* ATTR_SIZE */ + if (attr->ia_valid & ATTR_GID) + fsg.groups[fsg.ngroups++] = attr->ia_gid; + error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr, &fsg); if (error == 0) { nfs_refresh_inode(inode, &fattr); if ((attr->ia_valid & ATTR_MODE) != 0) { @@ -837,7 +844,7 @@ if (ctx != NULL) { atomic_set(&ctx->count, 1); ctx->dentry = dget(dentry); - ctx->cred = get_rpccred(cred); + ctx->cred = cred; ctx->state = NULL; ctx->lockowner = current->files; ctx->error = 0; @@ -917,11 +924,11 @@ { struct nfs_open_context *ctx; struct rpc_cred *cred; + struct rpc_groups fsg = { 1, { inode->i_gid } }; - if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL) + if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, &fsg, 0)) == NULL) return -ENOMEM; ctx = alloc_nfs_open_context(filp->f_dentry, cred); - put_rpccred(cred); if (ctx == NULL) return -ENOMEM; ctx->mode = filp->f_mode; @@ -1611,7 +1618,7 @@ } clnt->cl_chatty = 1; clp->cl_rpcclient = clnt; - clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0); + clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, NULL, 0); memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); nfs_idmap_new(clp); } diff -ru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c --- a/fs/nfs/nfs3proc.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/nfs3proc.c 2005-02-14 22:41:49.000000000 +0100 @@ -24,13 +24,21 @@ /* A wrapper to handle the EJUKEBOX error message */ static int -nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) +nfs3_rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, + struct rpc_cred *cred, int flags) { - sigset_t oldset; - int res; + struct rpc_message msg = { + .rpc_proc = &nfs3_procedures[proc], + .rpc_argp = argp, + .rpc_resp = resp, + .rpc_cred = cred, + }; + sigset_t oldset; + int res; + rpc_clnt_sigmask(clnt, &oldset); do { - res = rpc_call_sync(clnt, msg, flags); + res = rpc_call_sync(clnt, &msg, flags); if (res != -EJUKEBOX) break; set_current_state(TASK_INTERRUPTIBLE); @@ -41,21 +49,19 @@ return res; } -static inline int -nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) +static int +nfs3_rpc(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, + struct rpc_groups *fsg) { - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[proc], - .rpc_argp = argp, - .rpc_resp = resp, - }; - return nfs3_rpc_wrapper(clnt, &msg, flags); -} + struct rpc_cred *cred; + int res; -#define rpc_call(clnt, proc, argp, resp, flags) \ - nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags) -#define rpc_call_sync(clnt, msg, flags) \ - nfs3_rpc_wrapper(clnt, msg, flags) + if ((cred = rpcauth_lookupcred(clnt->cl_auth, fsg, 0)) == NULL) + return -ENOMEM; + res = nfs3_rpc_call(clnt, proc, argp, resp, cred, 0); + put_rpccred(cred); + return res; +} static int nfs3_async_handle_jukebox(struct rpc_task *task) @@ -79,10 +85,11 @@ dprintk("%s: call fsinfo\n", __FUNCTION__); info->fattr->valid = 0; - status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); + status = nfs3_rpc(server->client_sys, NFS3PROC_FSINFO, fhandle, info, NULL); dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); if (!(info->fattr->valid & NFS_ATTR_FATTR)) { - status = rpc_call(server->client_sys, NFS3PROC_GETATTR, fhandle, info->fattr, 0); + status = nfs3_rpc(server->client_sys, NFS3PROC_GETATTR, fhandle, + info->fattr, NULL); dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); } return status; @@ -99,15 +106,14 @@ dprintk("NFS call getattr\n"); fattr->valid = 0; - status = rpc_call(server->client, NFS3PROC_GETATTR, - fhandle, fattr, 0); + status = nfs3_rpc(server->client, NFS3PROC_GETATTR, fhandle, fattr, NULL); dprintk("NFS reply getattr: %d\n", status); return status; } static int nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, - struct iattr *sattr) + struct iattr *sattr, struct rpc_groups *fsg) { struct inode *inode = dentry->d_inode; struct nfs3_sattrargs arg = { @@ -118,14 +124,15 @@ dprintk("NFS call setattr\n"); fattr->valid = 0; - status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); + status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, fsg); dprintk("NFS reply setattr: %d\n", status); return status; } static int nfs3_proc_lookup(struct inode *dir, struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_diropargs arg = { @@ -143,10 +150,10 @@ dprintk("NFS call lookup %s\n", name->name); dir_attr.valid = 0; fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, fsg); if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, - fhandle, fattr, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_GETATTR, + fhandle, fattr, NULL); dprintk("NFS reply lookup: %d\n", status); if (status >= 0) status = nfs_refresh_inode(dir, &dir_attr); @@ -162,12 +169,6 @@ struct nfs3_accessres res = { .fattr = &fattr, }; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = entry->cred - }; int mode = entry->mask; int status; @@ -187,7 +188,8 @@ if (mode & MAY_EXEC) arg.access |= NFS3_ACCESS_EXECUTE; } - status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); + status = nfs3_rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, + &arg, &res, entry->cred, 0); nfs_refresh_inode(inode, &fattr); if (status == 0) { entry->mask = 0; @@ -216,8 +218,7 @@ dprintk("NFS call readlink\n"); fattr.valid = 0; - status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK, - &args, &fattr, 0); + status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_READLINK, &args, &fattr, NULL); nfs_refresh_inode(inode, &fattr); dprintk("NFS reply readlink: %d\n", status); return status; @@ -228,18 +229,13 @@ int flags = rdata->flags; struct inode * inode = rdata->inode; struct nfs_fattr * fattr = rdata->res.fattr; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_READ], - .rpc_argp = &rdata->args, - .rpc_resp = &rdata->res, - .rpc_cred = rdata->cred, - }; int status; dprintk("NFS call read %d @ %Ld\n", rdata->args.count, (long long) rdata->args.offset); fattr->valid = 0; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); + status = nfs3_rpc_call(NFS_CLIENT(inode), NFS3PROC_READ, + &rdata->args, &rdata->res, rdata->cred, flags); if (status >= 0) nfs_refresh_inode(inode, fattr); dprintk("NFS reply read: %d\n", status); @@ -251,18 +247,13 @@ int rpcflags = wdata->flags; struct inode * inode = wdata->inode; struct nfs_fattr * fattr = wdata->res.fattr; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], - .rpc_argp = &wdata->args, - .rpc_resp = &wdata->res, - .rpc_cred = wdata->cred, - }; int status; dprintk("NFS call write %d @ %Ld\n", wdata->args.count, (long long) wdata->args.offset); fattr->valid = 0; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); + status = nfs3_rpc_call(NFS_CLIENT(inode), NFS3PROC_WRITE, + &wdata->args, &wdata->res, wdata->cred, rpcflags); if (status >= 0) nfs_refresh_inode(inode, fattr); dprintk("NFS reply write: %d\n", status); @@ -273,18 +264,13 @@ { struct inode * inode = cdata->inode; struct nfs_fattr * fattr = cdata->res.fattr; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], - .rpc_argp = &cdata->args, - .rpc_resp = &cdata->res, - .rpc_cred = cdata->cred, - }; int status; dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, (long long) cdata->args.offset); fattr->valid = 0; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); + status = nfs3_rpc_call(NFS_CLIENT(inode), NFS3PROC_COMMIT, + &cdata->args, &cdata->res, cdata->cred, 0); if (status >= 0) nfs_refresh_inode(inode, fattr); dprintk("NFS reply commit: %d\n", status); @@ -297,7 +283,7 @@ */ static struct inode * nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, - int flags) + int flags, struct rpc_groups *fsg) { struct nfs_fh fhandle; struct nfs_fattr fattr; @@ -326,7 +312,7 @@ again: dir_attr.valid = 0; fattr.valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, fsg); nfs_refresh_inode(dir, &dir_attr); /* If the server doesn't support the exclusive creation semantics, @@ -353,7 +339,7 @@ if (status != 0) goto out; if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) { - status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr); + status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr, fsg); if (status != 0) goto out; } @@ -376,8 +362,8 @@ * not sure this buys us anything (and I'd have * to revamp the NFSv3 XDR code) */ fattr.valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR, - &arg, &fattr, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_SETATTR, + &arg, &fattr, NULL); dprintk("NFS reply setattr (post-create): %d\n", status); } if (status == 0) { @@ -392,7 +378,7 @@ } static int -nfs3_proc_remove(struct inode *dir, struct qstr *name) +nfs3_proc_remove(struct inode *dir, struct qstr *name, struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_diropargs arg = { @@ -400,16 +386,11 @@ .name = name->name, .len = name->len }; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE], - .rpc_argp = &arg, - .rpc_resp = &dir_attr, - }; int status; dprintk("NFS call remove %s\n", name->name); dir_attr.valid = 0; - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_REMOVE, &arg, &dir_attr, fsg); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply remove: %d\n", status); return status; @@ -454,7 +435,8 @@ static int nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, - struct inode *new_dir, struct qstr *new_name) + struct inode *new_dir, struct qstr *new_name, + struct rpc_groups *fsg) { struct nfs_fattr old_dir_attr, new_dir_attr; struct nfs3_renameargs arg = { @@ -474,7 +456,7 @@ dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); old_dir_attr.valid = 0; new_dir_attr.valid = 0; - status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, fsg); nfs_refresh_inode(old_dir, &old_dir_attr); nfs_refresh_inode(new_dir, &new_dir_attr); dprintk("NFS reply rename: %d\n", status); @@ -482,7 +464,8 @@ } static int -nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) +nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name, + struct rpc_groups *fsg) { struct nfs_fattr dir_attr, fattr; struct nfs3_linkargs arg = { @@ -500,7 +483,7 @@ dprintk("NFS call link %s\n", name->name); dir_attr.valid = 0; fattr.valid = 0; - status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, fsg); nfs_refresh_inode(dir, &dir_attr); nfs_refresh_inode(inode, &fattr); dprintk("NFS reply link: %d\n", status); @@ -510,7 +493,7 @@ static int nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_symlinkargs arg = { @@ -533,7 +516,7 @@ dprintk("NFS call symlink %s -> %s\n", name->name, path->name); dir_attr.valid = 0; fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, fsg); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply symlink: %d\n", status); return status; @@ -541,7 +524,8 @@ static int nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_mkdirargs arg = { @@ -560,14 +544,14 @@ dprintk("NFS call mkdir %s\n", name->name); dir_attr.valid = 0; fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, fsg); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply mkdir: %d\n", status); return status; } static int -nfs3_proc_rmdir(struct inode *dir, struct qstr *name) +nfs3_proc_rmdir(struct inode *dir, struct qstr *name, struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_diropargs arg = { @@ -579,7 +563,7 @@ dprintk("NFS call rmdir %s\n", name->name); dir_attr.valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, fsg); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply rmdir: %d\n", status); return status; @@ -614,24 +598,19 @@ .verf = verf, .plus = plus }; - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR], - .rpc_argp = &arg, - .rpc_resp = &res, - .rpc_cred = cred - }; int status; + u32 proc = NFS3PROC_READDIR; lock_kernel(); if (plus) - msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS]; + proc = NFS3PROC_READDIRPLUS; dprintk("NFS call readdir%s %d\n", plus? "plus" : "", (unsigned int) cookie); dir_attr.valid = 0; - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + status = nfs3_rpc_call(NFS_CLIENT(dir), proc, &arg, &res, cred, 0); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply readdir: %d\n", status); unlock_kernel(); @@ -640,7 +619,8 @@ static int nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, - dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr) + dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_fattr dir_attr; struct nfs3_mknodargs arg = { @@ -669,7 +649,7 @@ MAJOR(rdev), MINOR(rdev)); dir_attr.valid = 0; fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); + status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, fsg); nfs_refresh_inode(dir, &dir_attr); dprintk("NFS reply mknod: %d\n", status); return status; @@ -683,7 +663,7 @@ dprintk("NFS call fsstat\n"); stat->fattr->valid = 0; - status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0); + status = nfs3_rpc(server->client, NFS3PROC_FSSTAT, fhandle, stat, NULL); dprintk("NFS reply statfs: %d\n", status); return status; } @@ -696,7 +676,7 @@ dprintk("NFS call fsinfo\n"); info->fattr->valid = 0; - status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); + status = nfs3_rpc(server->client_sys, NFS3PROC_FSINFO, fhandle, info, NULL); dprintk("NFS reply fsinfo: %d\n", status); return status; } @@ -709,7 +689,7 @@ dprintk("NFS call pathconf\n"); info->fattr->valid = 0; - status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0); + status = nfs3_rpc(server->client, NFS3PROC_PATHCONF, fhandle, info, NULL); dprintk("NFS reply pathconf: %d\n", status); return status; } diff -ru a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c --- a/fs/nfs/nfs4proc.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/nfs4proc.c 2005-02-14 22:41:49.000000000 +0100 @@ -773,7 +773,7 @@ BUG_ON(nd->intent.open.flags & O_CREAT); } - cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, NULL, 0); state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); put_rpccred(cred); if (IS_ERR(state)) @@ -788,7 +788,7 @@ struct nfs4_state *state; struct inode *inode; - cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, NULL, 0); state = nfs4_open_delegated(dentry->d_inode, openflags, cred); if (IS_ERR(state)) state = nfs4_do_open(dir, dentry, openflags, NULL, cred); @@ -997,7 +997,7 @@ */ static int nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, - struct iattr *sattr) + struct iattr *sattr, struct rpc_groups *fsg) { struct inode * inode = dentry->d_inode; int size_change = sattr->ia_valid & ATTR_SIZE; @@ -1008,7 +1008,7 @@ fattr->valid = 0; if (size_change) { - struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); + struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, NULL, 0); state = nfs4_find_state(inode, cred, FMODE_WRITE); if (state == NULL) { state = nfs4_open_delegated(dentry->d_inode, @@ -1070,7 +1070,9 @@ return status; } -static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1317,13 +1319,13 @@ static struct inode * nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, - int flags) + int flags, struct rpc_groups *fsg) { struct inode *inode; struct nfs4_state *state = NULL; struct rpc_cred *cred; - cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, fsg, 0); state = nfs4_do_open(dir, dentry, flags, sattr, cred); put_rpccred(cred); if (!IS_ERR(state)) { @@ -1364,7 +1366,8 @@ return status; } -static int nfs4_proc_remove(struct inode *dir, struct qstr *name) +static int nfs4_proc_remove(struct inode *dir, struct qstr *name, + struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1441,7 +1444,8 @@ } static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, - struct inode *new_dir, struct qstr *new_name) + struct inode *new_dir, struct qstr *new_name, + struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1476,7 +1480,8 @@ return status; } -static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) +static int nfs4_proc_link(struct inode *inode, struct inode *dir, + struct qstr *name, struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1526,7 +1531,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1574,7 +1579,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -1682,7 +1687,7 @@ static int nfs4_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, dev_t rdev, struct nfs_fh *fh, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct nfs4_exception exception = { }; int err; @@ -2000,11 +2005,10 @@ /* Find our open stateid */ - cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, NULL, 0); if (unlikely(cred == NULL)) return -ENOMEM; ctx = alloc_nfs_open_context(dentry, cred); - put_rpccred(cred); if (unlikely(ctx == NULL)) return -ENOMEM; status = -EIO; /* ERACE actually */ diff -ru a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c --- a/fs/nfs/nfsroot.c 2004-05-10 04:32:54.000000000 +0200 +++ b/fs/nfs/nfsroot.c 2005-02-14 21:36:53.000000000 +0100 @@ -124,7 +124,6 @@ Opt_soft, Opt_hard, Opt_intr, Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp, - Opt_broken_suid, /* Error token */ Opt_err }; @@ -159,7 +158,6 @@ {Opt_udp, "udp"}, {Opt_tcp, "proto=tcp"}, {Opt_tcp, "tcp"}, - {Opt_broken_suid, "broken_suid"}, {Opt_err, NULL} }; @@ -268,9 +266,6 @@ case Opt_tcp: nfs_data.flags |= NFS_MOUNT_TCP; break; - case Opt_broken_suid: - nfs_data.flags |= NFS_MOUNT_BROKEN_SUID; - break; default : return 0; } diff -ru a/fs/nfs/proc.c b/fs/nfs/proc.c --- a/fs/nfs/proc.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/proc.c 2005-02-14 22:41:49.000000000 +0100 @@ -6,7 +6,7 @@ * OS-independent nfs remote procedure call functions * * Tuned by Alan Cox for >3K buffers - * so at last we can have decent(ish) throughput off a + * so at last we can have decent(ish) throughput off a * Sun server. * * Coding optimized and cleaned up by Florian La Roche. @@ -49,6 +49,33 @@ extern struct rpc_procinfo nfs_procedures[]; +static __inline__ int +nfs2_rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, + struct rpc_cred *cred, int flags) +{ + struct rpc_message msg = { + .rpc_proc = &nfs_procedures[proc], + .rpc_argp = argp, + .rpc_resp = resp, + .rpc_cred = cred, + }; + return rpc_call_sync(clnt, &msg, flags); +} + +static int +nfs2_rpc(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, + struct rpc_groups *fsg) +{ + struct rpc_cred *cred; + int res; + + if ((cred = rpcauth_lookupcred(clnt->cl_auth, fsg, 0)) == NULL) + return -ENOMEM; + res = nfs2_rpc_call(clnt, proc, argp, resp, cred, 0); + put_rpccred(cred); + return res; +} + /* * Bare-bones access to getattr: this is for nfs_read_super. */ @@ -62,12 +89,12 @@ dprintk("%s: call getattr\n", __FUNCTION__); fattr->valid = 0; - status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0); + status = nfs2_rpc(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, NULL); dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); if (status) return status; dprintk("%s: call statfs\n", __FUNCTION__); - status = rpc_call(server->client_sys, NFSPROC_STATFS, fhandle, &fsinfo, 0); + status = nfs2_rpc(server->client_sys, NFSPROC_STATFS, fhandle, &fsinfo, NULL); dprintk("%s: reply statfs: %d\n", __FUNCTION__, status); if (status) return status; @@ -94,18 +121,17 @@ dprintk("NFS call getattr\n"); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_GETATTR, - fhandle, fattr, 0); + status = nfs2_rpc(server->client, NFSPROC_GETATTR, fhandle, fattr, NULL); dprintk("NFS reply getattr: %d\n", status); return status; } static int nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, - struct iattr *sattr) + struct iattr *sattr, struct rpc_groups *fsg) { struct inode *inode = dentry->d_inode; - struct nfs_sattrargs arg = { + struct nfs_sattrargs arg = { .fh = NFS_FH(inode), .sattr = sattr }; @@ -113,14 +139,15 @@ dprintk("NFS call setattr\n"); fattr->valid = 0; - status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); + status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, fsg); dprintk("NFS reply setattr: %d\n", status); return status; } static int nfs_proc_lookup(struct inode *dir, struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_diropargs arg = { .fh = NFS_FH(dir), @@ -135,7 +162,7 @@ dprintk("NFS call lookup %s\n", name->name); fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, fsg); dprintk("NFS reply lookup: %d\n", status); return status; } @@ -152,7 +179,7 @@ int status; dprintk("NFS call readlink\n"); - status = rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK, &args, NULL, 0); + status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_READLINK, &args, NULL, NULL); dprintk("NFS reply readlink: %d\n", status); return status; } @@ -162,18 +189,13 @@ int flags = rdata->flags; struct inode * inode = rdata->inode; struct nfs_fattr * fattr = rdata->res.fattr; - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_READ], - .rpc_argp = &rdata->args, - .rpc_resp = &rdata->res, - .rpc_cred = rdata->cred, - }; int status; dprintk("NFS call read %d @ %Ld\n", rdata->args.count, (long long) rdata->args.offset); fattr->valid = 0; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); + status = nfs2_rpc_call(NFS_CLIENT(inode), NFSPROC_READ, &rdata->args, + &rdata->res, rdata->cred, flags); if (status >= 0) { nfs_refresh_inode(inode, fattr); /* Emulate the eof flag, which isn't normally needed in NFSv2 @@ -191,18 +213,13 @@ int flags = wdata->flags; struct inode * inode = wdata->inode; struct nfs_fattr * fattr = wdata->res.fattr; - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_WRITE], - .rpc_argp = &wdata->args, - .rpc_resp = &wdata->res, - .rpc_cred = wdata->cred, - }; int status; dprintk("NFS call write %d @ %Ld\n", wdata->args.count, (long long) wdata->args.offset); fattr->valid = 0; - status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); + status = nfs2_rpc_call(NFS_CLIENT(inode), NFSPROC_WRITE, &wdata->args, + &wdata->res, wdata->cred, flags); if (status >= 0) { nfs_refresh_inode(inode, fattr); wdata->res.count = wdata->args.count; @@ -214,7 +231,7 @@ static struct inode * nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, - int flags) + int flags, struct rpc_groups *fsg) { struct nfs_fh fhandle; struct nfs_fattr fattr; @@ -232,7 +249,7 @@ fattr.valid = 0; dprintk("NFS call create %s\n", dentry->d_name.name); - status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg); dprintk("NFS reply create: %d\n", status); if (status == 0) { struct inode *inode; @@ -249,7 +266,8 @@ */ static int nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, - dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr) + dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_createargs arg = { .fh = NFS_FH(dir), @@ -275,35 +293,29 @@ } fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg); if (status == -EINVAL && S_ISFIFO(mode)) { sattr->ia_mode = mode; fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg); } dprintk("NFS reply mknod: %d\n", status); return status; } - + static int -nfs_proc_remove(struct inode *dir, struct qstr *name) +nfs_proc_remove(struct inode *dir, struct qstr *name, struct rpc_groups *fsg) { struct nfs_diropargs arg = { .fh = NFS_FH(dir), .name = name->name, .len = name->len }; - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], - .rpc_argp = &arg, - .rpc_resp = NULL, - .rpc_cred = NULL - }; int status; dprintk("NFS call remove %s\n", name->name); - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_REMOVE, &arg, NULL, fsg); dprintk("NFS reply remove: %d\n", status); return status; @@ -337,7 +349,8 @@ static int nfs_proc_rename(struct inode *old_dir, struct qstr *old_name, - struct inode *new_dir, struct qstr *new_name) + struct inode *new_dir, struct qstr *new_name, + struct rpc_groups *fsg) { struct nfs_renameargs arg = { .fromfh = NFS_FH(old_dir), @@ -350,13 +363,14 @@ int status; dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); - status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0); + status = nfs2_rpc(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, fsg); dprintk("NFS reply rename: %d\n", status); return status; } static int -nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) +nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name, + struct rpc_groups *fsg) { struct nfs_linkargs arg = { .fromfh = NFS_FH(inode), @@ -367,7 +381,7 @@ int status; dprintk("NFS call link %s\n", name->name); - status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); + status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, fsg); dprintk("NFS reply link: %d\n", status); return status; } @@ -375,7 +389,7 @@ static int nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, struct rpc_groups *fsg) { struct nfs_symlinkargs arg = { .fromfh = NFS_FH(dir), @@ -392,14 +406,15 @@ dprintk("NFS call symlink %s -> %s\n", name->name, path->name); fattr->valid = 0; fhandle->size = 0; - status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, fsg); dprintk("NFS reply symlink: %d\n", status); return status; } static int nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct rpc_groups *fsg) { struct nfs_createargs arg = { .fh = NFS_FH(dir), @@ -415,13 +430,13 @@ dprintk("NFS call mkdir %s\n", name->name); fattr->valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, fsg); dprintk("NFS reply mkdir: %d\n", status); return status; } static int -nfs_proc_rmdir(struct inode *dir, struct qstr *name) +nfs_proc_rmdir(struct inode *dir, struct qstr *name, struct rpc_groups *fsg) { struct nfs_diropargs arg = { .fh = NFS_FH(dir), @@ -431,7 +446,7 @@ int status; dprintk("NFS call rmdir %s\n", name->name); - status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0); + status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, fsg); dprintk("NFS reply rmdir: %d\n", status); return status; } @@ -454,18 +469,12 @@ .count = count, .pages = &page }; - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_READDIR], - .rpc_argp = &arg, - .rpc_resp = NULL, - .rpc_cred = cred - }; int status; lock_kernel(); dprintk("NFS call readdir %d\n", (unsigned int)cookie); - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + status = nfs2_rpc_call(NFS_CLIENT(dir), NFSPROC_READDIR, &arg, NULL, cred, 0); dprintk("NFS reply readdir: %d\n", status); unlock_kernel(); @@ -481,7 +490,7 @@ dprintk("NFS call statfs\n"); stat->fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); + status = nfs2_rpc(server->client, NFSPROC_STATFS, fhandle, &fsinfo, NULL); dprintk("NFS reply statfs: %d\n", status); if (status) goto out; @@ -504,7 +513,7 @@ dprintk("NFS call fsinfo\n"); info->fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); + status = nfs2_rpc(server->client, NFSPROC_STATFS, fhandle, &fsinfo, NULL); dprintk("NFS reply fsinfo: %d\n", status); if (status) goto out; diff -ru a/fs/nfs/unlink.c b/fs/nfs/unlink.c --- a/fs/nfs/unlink.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfs/unlink.c 2005-02-14 22:41:49.000000000 +0100 @@ -160,6 +160,7 @@ struct nfs_unlinkdata *data; struct rpc_task *task; struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode); + struct rpc_groups fsg = { 1, { dir->d_inode->i_gid } }; int status = -ENOMEM; data = kmalloc(sizeof(*data), GFP_KERNEL); @@ -183,7 +184,7 @@ spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; spin_unlock(&dentry->d_lock); - data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); + data->cred = rpcauth_lookupcred(clnt->cl_auth, &fsg, 0); rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL); status = 0; diff -ru a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c --- a/fs/nfsd/nfs4callback.c 2005-02-06 18:05:04.000000000 +0100 +++ b/fs/nfsd/nfs4callback.c 2005-02-14 22:36:56.000000000 +0100 @@ -351,19 +351,18 @@ { struct auth_cred acred; struct rpc_clnt *clnt = clp->cl_callback.cb_client; + struct svc_cred *cr = &clp->cl_cred; struct rpc_cred *ret = NULL; if (!clnt) goto out; - get_group_info(clp->cl_cred.cr_group_info); - acred.uid = clp->cl_cred.cr_uid; - acred.gid = clp->cl_cred.cr_gid; - acred.group_info = clp->cl_cred.cr_group_info; - + acred.uid = cr->cr_uid; dprintk("NFSD: looking up %s cred\n", clnt->cl_auth->au_ops->au_name); + if (clnt->cl_auth->au_ops->cr_add_groups) + clnt->cl_auth->au_ops->cr_add_groups(&acred, cr->cr_gid, cr->cr_group_info, NULL); ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags); - put_group_info(clp->cl_cred.cr_group_info); + dprintk("NFSD: cred %p\n", ret); out: return ret; } diff -ru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h --- a/include/linux/nfs_xdr.h 2005-02-06 18:05:11.000000000 +0100 +++ b/include/linux/nfs_xdr.h 2005-02-14 22:41:49.000000000 +0100 @@ -660,7 +660,7 @@ struct nfs_access_entry; /* - * RPC procedure vector for NFSv2/NFSv3 demuxing + * RPC procedure vector for NFSv2/NFSv3/NFSv4 demuxing */ struct nfs_rpc_ops { int version; /* Protocol version */ @@ -672,9 +672,9 @@ int (*getattr) (struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); int (*setattr) (struct dentry *, struct nfs_fattr *, - struct iattr *); - int (*lookup) (struct inode *, struct qstr *, - struct nfs_fh *, struct nfs_fattr *); + struct iattr *, struct rpc_groups *); + int (*lookup) (struct inode *, struct qstr *, struct nfs_fh *, + struct nfs_fattr *, struct rpc_groups *); int (*access) (struct inode *, struct nfs_access_entry *); int (*readlink)(struct inode *, struct page *, unsigned int, unsigned int); @@ -682,24 +682,27 @@ int (*write) (struct nfs_write_data *); int (*commit) (struct nfs_write_data *); struct inode * (*create) (struct inode *, struct dentry *, - struct iattr *, int); - int (*remove) (struct inode *, struct qstr *); + struct iattr *, int, struct rpc_groups *); + int (*remove) (struct inode *, struct qstr *, struct rpc_groups *); int (*unlink_setup) (struct rpc_message *, struct dentry *, struct qstr *); int (*unlink_done) (struct dentry *, struct rpc_task *); int (*rename) (struct inode *, struct qstr *, - struct inode *, struct qstr *); - int (*link) (struct inode *, struct inode *, struct qstr *); + struct inode *, struct qstr *, struct rpc_groups *); + int (*link) (struct inode *, struct inode *, struct qstr *, + struct rpc_groups *); int (*symlink) (struct inode *, struct qstr *, struct qstr *, struct iattr *, struct nfs_fh *, - struct nfs_fattr *); + struct nfs_fattr *, struct rpc_groups *); int (*mkdir) (struct inode *, struct qstr *, struct iattr *, - struct nfs_fh *, struct nfs_fattr *); - int (*rmdir) (struct inode *, struct qstr *); + struct nfs_fh *, struct nfs_fattr *, + struct rpc_groups *); + int (*rmdir) (struct inode *, struct qstr *, struct rpc_groups *); int (*readdir) (struct dentry *, struct rpc_cred *, u64, struct page *, unsigned int, int); int (*mknod) (struct inode *, struct qstr *, struct iattr *, - dev_t, struct nfs_fh *, struct nfs_fattr *); + dev_t, struct nfs_fh *, struct nfs_fattr *, + struct rpc_groups *); int (*statfs) (struct nfs_server *, struct nfs_fh *, struct nfs_fsstat *); int (*fsinfo) (struct nfs_server *, struct nfs_fh *, diff -ru a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h --- a/include/linux/sunrpc/auth.h 2005-02-06 18:05:11.000000000 +0100 +++ b/include/linux/sunrpc/auth.h 2005-02-14 23:07:16.000000000 +0100 @@ -12,6 +12,7 @@ #ifdef __KERNEL__ #include +#include #include #include #include @@ -24,11 +25,16 @@ /* Maximum size (in bytes) of an rpc credential or verifier */ #define RPC_MAX_AUTH_SIZE (400) +struct rpc_groups { + int ngroups; + gid_t groups[RPC_MAXGROUPS]; +}; + /* Work around the lack of a VFS credential */ struct auth_cred { - uid_t uid; - gid_t gid; - struct group_info *group_info; + uid_t uid; + gid_t gid; + struct rpc_groups rg; }; /* @@ -92,13 +98,14 @@ void (*destroy)(struct rpc_auth *); struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); + void (*cr_add_groups)(struct auth_cred *, gid_t, struct group_info *, struct rpc_groups *); }; struct rpc_credops { void (*crdestroy)(struct rpc_cred *); int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); - u32 * (*crmarshal)(struct rpc_task *, u32 *, int); + u32 * (*crmarshal)(struct rpc_task *, u32 *); int (*crrefresh)(struct rpc_task *); u32 * (*crvalidate)(struct rpc_task *, u32 *); int (*crwrap_req)(struct rpc_task *, kxdrproc_t, @@ -118,11 +125,8 @@ struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); void rpcauth_destroy(struct rpc_auth *); struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int); -struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); -struct rpc_cred * rpcauth_bindcred(struct rpc_task *); -void rpcauth_holdcred(struct rpc_task *); +struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, struct rpc_groups *, int); void put_rpccred(struct rpc_cred *); -void rpcauth_unbindcred(struct rpc_task *); u32 * rpcauth_marshcred(struct rpc_task *, u32 *); u32 * rpcauth_checkverf(struct rpc_task *, u32 *); int rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, u32 *data, void *obj); diff -ru a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h --- a/include/linux/sunrpc/clnt.h 2004-05-10 04:32:39.000000000 +0200 +++ b/include/linux/sunrpc/clnt.h 2005-02-14 21:36:53.000000000 +0100 @@ -51,7 +51,6 @@ cl_intr : 1,/* interruptible */ cl_chatty : 1,/* be verbose */ cl_autobind : 1,/* use getport() */ - cl_droppriv : 1,/* enable NFS suid hack */ cl_oneshot : 1,/* dispose after use */ cl_dead : 1;/* abandoned */ diff -ru a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h --- a/include/linux/sunrpc/msg_prot.h 2004-05-10 04:32:54.000000000 +0200 +++ b/include/linux/sunrpc/msg_prot.h 2005-02-14 21:36:53.000000000 +0100 @@ -75,6 +75,7 @@ #define RPC_PMAP_PORT 111 #define RPC_MAXNETNAMELEN 256 +#define RPC_MAXGROUPS 16 #endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ diff -ru a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h --- a/include/linux/sunrpc/sched.h 2005-02-06 18:05:11.000000000 +0100 +++ b/include/linux/sunrpc/sched.h 2005-02-14 21:36:53.000000000 +0100 @@ -53,9 +53,8 @@ struct rpc_message tk_msg; /* RPC call info */ __u32 * tk_buffer; /* XDR buffer */ size_t tk_bufsize; - __u8 tk_garb_retry, - tk_cred_retry, - tk_suid_retry; + __u8 tk_garb_retry; + __u8 tk_cred_retry; unsigned long tk_cookie; /* Cookie for batching tasks */ @@ -118,9 +117,7 @@ */ #define RPC_TASK_ASYNC 0x0001 /* is an async task */ #define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */ -#define RPC_TASK_SETUID 0x0004 /* is setuid process */ #define RPC_TASK_CHILD 0x0008 /* is child of other task */ -#define RPC_CALL_REALUID 0x0010 /* try using real uid */ #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ #define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */ #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ @@ -129,7 +126,6 @@ #define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */ #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) -#define RPC_IS_SETUID(t) ((t)->tk_flags & RPC_TASK_SETUID) #define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD) #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) diff -ru a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h --- a/include/linux/sunrpc/svcauth.h 2004-08-15 12:38:54.000000000 +0200 +++ b/include/linux/sunrpc/svcauth.h 2005-02-14 21:36:53.000000000 +0100 @@ -16,7 +16,6 @@ #include #include -#define SVC_CRED_NGROUPS 32 struct svc_cred { uid_t cr_uid; gid_t cr_gid; diff -ru a/net/sunrpc/auth.c b/net/sunrpc/auth.c --- a/net/sunrpc/auth.c 2005-02-06 18:05:16.000000000 +0100 +++ b/net/sunrpc/auth.c 2005-02-14 22:15:03.000000000 +0100 @@ -247,59 +247,27 @@ } } - return (struct rpc_cred *) cred; + return cred; } struct rpc_cred * -rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) +rpcauth_lookupcred(struct rpc_auth *auth, struct rpc_groups *rg, int taskflags) { struct auth_cred acred; struct rpc_cred *ret; - get_group_info(current->group_info); - acred.uid = current->fsuid; - acred.gid = current->fsgid; - acred.group_info = current->group_info; + dprintk("RPC: looking up %s cred\n", auth->au_ops->au_name); - dprintk("RPC: looking up %s cred\n", - auth->au_ops->au_name); - ret = rpcauth_lookup_credcache(auth, &acred, taskflags); - put_group_info(current->group_info); - return ret; -} - -struct rpc_cred * -rpcauth_bindcred(struct rpc_task *task) -{ - struct rpc_auth *auth = task->tk_auth; - struct auth_cred acred; - struct rpc_cred *ret; - - get_group_info(current->group_info); acred.uid = current->fsuid; - acred.gid = current->fsgid; - acred.group_info = current->group_info; + if (auth->au_ops->cr_add_groups) + auth->au_ops->cr_add_groups(&acred, current->fsgid, current->group_info, rg); + ret = rpcauth_lookup_credcache(auth, &acred, taskflags); - dprintk("RPC: %4d looking up %s cred\n", - task->tk_pid, task->tk_auth->au_ops->au_name); - task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags); - if (task->tk_msg.rpc_cred == 0) - task->tk_status = -ENOMEM; - ret = task->tk_msg.rpc_cred; - put_group_info(current->group_info); + dprintk("RPC: cred %p\n", ret); return ret; } void -rpcauth_holdcred(struct rpc_task *task) -{ - dprintk("RPC: %4d holding %s cred %p\n", - task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred); - if (task->tk_msg.rpc_cred) - get_rpccred(task->tk_msg.rpc_cred); -} - -void put_rpccred(struct rpc_cred *cred) { if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) @@ -314,19 +282,6 @@ spin_unlock(&rpc_credcache_lock); } -void -rpcauth_unbindcred(struct rpc_task *task) -{ - struct rpc_auth *auth = task->tk_auth; - struct rpc_cred *cred = task->tk_msg.rpc_cred; - - dprintk("RPC: %4d releasing %s cred %p\n", - task->tk_pid, auth->au_ops->au_name, cred); - - put_rpccred(cred); - task->tk_msg.rpc_cred = NULL; -} - u32 * rpcauth_marshcred(struct rpc_task *task, u32 *p) { @@ -335,8 +290,7 @@ dprintk("RPC: %4d marshaling %s cred %p\n", task->tk_pid, auth->au_ops->au_name, cred); - return cred->cr_ops->crmarshal(task, p, - task->tk_flags & RPC_CALL_REALUID); + return cred->cr_ops->crmarshal(task, p); } u32 * diff -ru a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c --- a/net/sunrpc/auth_gss/auth_gss.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/auth_gss/auth_gss.c 2005-02-14 21:36:53.000000000 +0100 @@ -63,8 +63,6 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif -#define NFS_NGROUPS 16 - #define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */ #define GSS_CRED_SLACK 1024 /* XXX: unused */ /* length of a krb5 verifier (48), plus data added before arguments when @@ -692,7 +690,7 @@ * Maybe we should keep a cached credential for performance reasons. */ static u32 * -gss_marshal(struct rpc_task *task, u32 *p, int ruid) +gss_marshal(struct rpc_task *task, u32 *p) { struct rpc_cred *cred = task->tk_msg.rpc_cred; struct gss_cred *gss_cred = container_of(cred, struct gss_cred, diff -ru a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c --- a/net/sunrpc/auth_null.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/auth_null.c 2005-02-14 21:36:53.000000000 +0100 @@ -84,7 +84,7 @@ * Marshal credential. */ static u32 * -nul_marshal(struct rpc_task *task, u32 *p, int ruid) +nul_marshal(struct rpc_task *task, u32 *p) { *p++ = htonl(RPC_AUTH_NULL); *p++ = 0; diff -ru a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c --- a/net/sunrpc/auth_unix.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/auth_unix.c 2005-02-14 23:38:29.000000000 +0100 @@ -14,14 +14,10 @@ #include #include -#define NFS_NGROUPS 16 - struct unx_cred { struct rpc_cred uc_base; gid_t uc_gid; - uid_t uc_puid; /* process uid */ - gid_t uc_pgid; /* process gid */ - gid_t uc_gids[NFS_NGROUPS]; + gid_t uc_gids[RPC_MAXGROUPS]; }; #define uc_uid uc_base.cr_uid #define uc_count uc_base.cr_count @@ -34,6 +30,7 @@ #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH +# define RG(rg,i) ((i) < (rg).ngroups ? (int)(rg).groups[i] : -1) #endif static struct rpc_credops unix_credops; @@ -67,7 +64,6 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { struct unx_cred *cred; - int i; dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", acred->uid, acred->gid); @@ -78,28 +74,58 @@ atomic_set(&cred->uc_count, 0); cred->uc_flags = RPCAUTH_CRED_UPTODATE; if (flags & RPC_TASK_ROOTCREDS) { - cred->uc_uid = cred->uc_puid = 0; - cred->uc_gid = cred->uc_pgid = 0; + cred->uc_uid = 0; + cred->uc_gid = 0; cred->uc_gids[0] = NOGROUP; } else { - int groups = acred->group_info->ngroups; - if (groups > NFS_NGROUPS) - groups = NFS_NGROUPS; - + int n = acred->rg.ngroups; cred->uc_uid = acred->uid; cred->uc_gid = acred->gid; - cred->uc_puid = current->uid; - cred->uc_pgid = current->gid; - for (i = 0; i < groups; i++) - cred->uc_gids[i] = GROUP_AT(acred->group_info, i); - if (i < NFS_NGROUPS) - cred->uc_gids[i] = NOGROUP; + memcpy(cred->uc_gids, acred->rg.groups, n * sizeof (gid_t)); + if (n < RPC_MAXGROUPS) + cred->uc_gids[n] = NOGROUP; } cred->uc_base.cr_ops = &unix_credops; return (struct rpc_cred *) cred; } +/* + * Add groups to acred. When there are too many then try to be smart by + * picking only the relevant ones from our secondary group list. + */ +static void +unx_add_groups(struct auth_cred *acred, gid_t gid, struct group_info *gi, struct rpc_groups *rg) +{ + int i, n; + + acred->gid = gid; + get_group_info(gi); + n = gi->ngroups; + if (n <= RPC_MAXGROUPS) + rg = NULL; + else + n = RPC_MAXGROUPS; /* too many groups for AUTH_UNIX */ + if (rg) { + n = 0; /* pick the few relevant groups we're a member of */ + for (i = 0; i < rg->ngroups; ++i) { + gid = rg->groups[i]; + if (in_group_p(gid)) + acred->rg.groups[n++] = gid; + } + acred->rg.ngroups = n; + dprintk("RPC: unx_add_groups(): rg=%d:%d,%d,%d -> %d:%d,%d,%d\n", + rg->ngroups, RG(*rg, 0), RG(*rg, 1), RG(*rg, 2), + n, RG(acred->rg, 0), RG(acred->rg, 1), RG(acred->rg, 2)); + } else { + dprintk("RPC: unx_add_groups(): ngroups=%d\n", gi->ngroups); + for (i = 0; i < n; ++i) + acred->rg.groups[i] = GROUP_AT(gi, i); + acred->rg.ngroups = n; + } + put_group_info(gi); +} + static void unx_destroy_cred(struct rpc_cred *cred) { @@ -115,27 +141,22 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) { struct unx_cred *cred = (struct unx_cred *) rcred; - int i; if (!(taskflags & RPC_TASK_ROOTCREDS)) { - int groups; + int n = acred->rg.ngroups; if (cred->uc_uid != acred->uid - || cred->uc_gid != acred->gid - || cred->uc_puid != current->uid - || cred->uc_pgid != current->gid) + || cred->uc_gid != acred->gid) return 0; - groups = acred->group_info->ngroups; - if (groups > NFS_NGROUPS) - groups = NFS_NGROUPS; - for (i = 0; i < groups ; i++) - if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) - return 0; - return 1; + if (n < RPC_MAXGROUPS && cred->uc_gids[n] != NOGROUP) + return 0; + + return !memcmp(cred->uc_gids, acred->rg.groups, + n * sizeof (gid_t)); } - return (cred->uc_uid == 0 && cred->uc_puid == 0 - && cred->uc_gid == 0 && cred->uc_pgid == 0 + return (cred->uc_uid == 0 + && cred->uc_gid == 0 && cred->uc_gids[0] == (gid_t) NOGROUP); } @@ -144,7 +165,7 @@ * Maybe we should keep a cached credential for performance reasons. */ static u32 * -unx_marshal(struct rpc_task *task, u32 *p, int ruid) +unx_marshal(struct rpc_task *task, u32 *p) { struct rpc_clnt *clnt = task->tk_client; struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred; @@ -160,16 +181,10 @@ */ p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); - /* Note: we don't use real uid if it involves raising privilege */ - if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) { - *p++ = htonl((u32) cred->uc_puid); - *p++ = htonl((u32) cred->uc_pgid); - } else { - *p++ = htonl((u32) cred->uc_uid); - *p++ = htonl((u32) cred->uc_gid); - } + *p++ = htonl((u32) cred->uc_uid); + *p++ = htonl((u32) cred->uc_gid); hold = p++; - for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++) + for (i = 0; i < RPC_MAXGROUPS && cred->uc_gids[i] != (gid_t) NOGROUP; i++) *p++ = htonl((u32) cred->uc_gids[i]); *hold = htonl(p - hold - 1); /* gid array length */ *base = htonl((p - base - 1) << 2); /* cred length */ @@ -224,6 +239,7 @@ .create = unx_create, .destroy = unx_destroy, .crcreate = unx_create_cred, + .cr_add_groups = unx_add_groups, }; static diff -ru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c --- a/net/sunrpc/clnt.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/clnt.c 2005-02-14 21:38:41.000000000 +0100 @@ -425,11 +425,15 @@ { task->tk_msg = *msg; task->tk_flags |= flags; - /* Bind the user cred */ - if (task->tk_msg.rpc_cred != NULL) { - rpcauth_holdcred(task); - } else - rpcauth_bindcred(task); + + if (task->tk_msg.rpc_cred) { + /* we copied msg->rpc_cred, hold it */ + get_rpccred(task->tk_msg.rpc_cred); + } else { + task->tk_msg.rpc_cred = rpcauth_lookupcred(task->tk_auth, NULL, task->tk_flags); + if (task->tk_msg.rpc_cred == NULL) + task->tk_status = -ENOMEM; + } if (task->tk_status == 0) task->tk_action = call_start; @@ -871,21 +875,6 @@ goto out_retry; } - /* - * The following is an NFS-specific hack to cater for setuid - * processes whose uid is mapped to nobody on the server. - */ - if (task->tk_client->cl_droppriv && - (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) { - if (RPC_IS_SETUID(task) && task->tk_suid_retry) { - dprintk("RPC: %4d retry squashed uid\n", task->tk_pid); - task->tk_flags ^= RPC_CALL_REALUID; - task->tk_action = call_bind; - task->tk_suid_retry--; - goto out_retry; - } - } - task->tk_action = NULL; if (decode) diff -ru a/net/sunrpc/sched.c b/net/sunrpc/sched.c --- a/net/sunrpc/sched.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/sched.c 2005-02-14 21:37:34.000000000 +0100 @@ -747,13 +747,10 @@ task->tk_client = clnt; task->tk_flags = flags; task->tk_exit = callback; - if (current->uid != current->fsuid || current->gid != current->fsgid) - task->tk_flags |= RPC_TASK_SETUID; /* Initialize retry counters */ task->tk_garb_retry = 2; task->tk_cred_retry = 2; - task->tk_suid_retry = 1; task->tk_priority = RPC_PRIORITY_NORMAL; task->tk_cookie = (unsigned long)current; @@ -854,8 +851,10 @@ /* Release resources */ if (task->tk_rqstp) xprt_release(task); - if (task->tk_msg.rpc_cred) - rpcauth_unbindcred(task); + if (task->tk_msg.rpc_cred) { + put_rpccred(task->tk_msg.rpc_cred); + task->tk_msg.rpc_cred = NULL; + } rpc_free(task); if (task->tk_client) { rpc_release_client(task->tk_client); diff -ru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c --- a/net/sunrpc/svcauth_unix.c 2005-02-06 18:05:17.000000000 +0100 +++ b/net/sunrpc/svcauth_unix.c 2005-02-14 21:36:53.000000000 +0100 @@ -459,7 +459,7 @@ cred->cr_uid = ntohl(svc_getu32(argv)); /* uid */ cred->cr_gid = ntohl(svc_getu32(argv)); /* gid */ slen = ntohl(svc_getu32(argv)); /* gids length */ - if (slen > 16 || (len -= (slen + 2)*4) < 0) + if (slen > RPC_MAXGROUPS || (len -= (slen + 2)*4) < 0) goto badcred; cred->cr_group_info = groups_alloc(slen); if (cred->cr_group_info == NULL)