From: Neil Brown Tidy up new groups handling in nfsd. Set up the group_info structure when decoding the RPC packet instead of in nfsd. --- fs/nfsd/auth.c | 45 +++++++++-------------------------------- fs/nfsd/nfs4state.c | 7 +++--- fs/nfsd/nfsfh.c | 6 ++++- include/linux/sunrpc/svcauth.h | 2 - net/sunrpc/svcauth_unix.c | 21 +++++++++++-------- 5 files changed, 33 insertions(+), 48 deletions(-) diff -puN fs/nfsd/auth.c~nfsd-NGROUPS-fixes fs/nfsd/auth.c --- 25/fs/nfsd/auth.c~nfsd-NGROUPS-fixes 2004-02-24 22:20:59.000000000 -0800 +++ 25-akpm/fs/nfsd/auth.c 2004-02-24 22:20:59.000000000 -0800 @@ -15,35 +15,21 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) { struct svc_cred *cred = &rqstp->rq_cred; - struct group_info *group_info; - int ngroups; int i; int ret; - ngroups = 0; - if (!(exp->ex_flags & NFSEXP_ALLSQUASH)) { - for (i = 0; i < SVC_CRED_NGROUPS; i++) { - if (cred->cr_groups[i] == (gid_t)NOGROUP) - break; - ngroups++; - } - } - group_info = groups_alloc(ngroups); - if (group_info == NULL) - return -ENOMEM; - if (exp->ex_flags & NFSEXP_ALLSQUASH) { cred->cr_uid = exp->ex_anon_uid; cred->cr_gid = exp->ex_anon_gid; - cred->cr_groups[0] = NOGROUP; + cred->cr_group_info->ngroups = 0; } else if (exp->ex_flags & NFSEXP_ROOTSQUASH) { if (!cred->cr_uid) cred->cr_uid = exp->ex_anon_uid; if (!cred->cr_gid) cred->cr_gid = exp->ex_anon_gid; - for (i = 0; i < SVC_CRED_NGROUPS; i++) - if (!cred->cr_groups[i]) - cred->cr_groups[i] = exp->ex_anon_gid; + for (i = 0; i < cred->cr_group_info->ngroups; i++) + if (!GROUP_AT(cred->cr_group_info, i)) + GROUP_AT(cred->cr_group_info, i) = exp->ex_anon_gid; } if (cred->cr_uid != (uid_t) -1) @@ -55,23 +41,12 @@ int nfsd_setuser(struct svc_rqst *rqstp, else current->fsgid = exp->ex_anon_gid; - for (i = 0; i < SVC_CRED_NGROUPS; i++) { - gid_t group = cred->cr_groups[i]; - if (group == (gid_t) NOGROUP) - break; - GROUP_AT(group_info, i) = group; + ret = set_current_groups(cred->cr_group_info); + if ((cred->cr_uid)) { + cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; + } else { + cap_t(current->cap_effective) |= (CAP_NFSD_MASK & + current->cap_permitted); } - - ret = set_current_groups(group_info); - if (ret == 0) { - if ((cred->cr_uid)) { - cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; - } else { - cap_t(current->cap_effective) |= (CAP_NFSD_MASK & - current->cap_permitted); - } - } - put_group_info(group_info); - return ret; } diff -puN fs/nfsd/nfs4state.c~nfsd-NGROUPS-fixes fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~nfsd-NGROUPS-fixes 2004-02-24 22:20:59.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4state.c 2004-02-24 22:20:59.000000000 -0800 @@ -193,6 +193,8 @@ alloc_client(struct xdr_netobj name) static inline void free_client(struct nfs4_client *clp) { + if (clp->cl_cred.cr_group_info) + put_group_info(clp->cl_cred.cr_group_info); kfree(clp->cl_name.data); kfree(clp); } @@ -240,12 +242,11 @@ copy_clid(struct nfs4_client *target, st static void copy_cred(struct svc_cred *target, struct svc_cred *source) { - int i; target->cr_uid = source->cr_uid; target->cr_gid = source->cr_gid; - for(i = 0; i < SVC_CRED_NGROUPS; i++) - target->cr_groups[i] = source->cr_groups[i]; + target->cr_group_info = source->cr_group_info; + get_group_info(target->cr_group_info); } static int diff -puN fs/nfsd/nfsfh.c~nfsd-NGROUPS-fixes fs/nfsd/nfsfh.c --- 25/fs/nfsd/nfsfh.c~nfsd-NGROUPS-fixes 2004-02-24 22:20:59.000000000 -0800 +++ 25-akpm/fs/nfsd/nfsfh.c 2004-02-24 22:20:59.000000000 -0800 @@ -165,7 +165,11 @@ fh_verify(struct svc_rqst *rqstp, struct } /* Set user creds for this exportpoint */ - nfsd_setuser(rqstp, exp); + error = nfsd_setuser(rqstp, exp); + if (error) { + error = nfserrno(error); + goto out; + } /* * Look up the dentry using the NFS file handle. diff -puN include/linux/sunrpc/svcauth.h~nfsd-NGROUPS-fixes include/linux/sunrpc/svcauth.h --- 25/include/linux/sunrpc/svcauth.h~nfsd-NGROUPS-fixes 2004-02-24 22:20:59.000000000 -0800 +++ 25-akpm/include/linux/sunrpc/svcauth.h 2004-02-24 22:20:59.000000000 -0800 @@ -20,7 +20,7 @@ struct svc_cred { uid_t cr_uid; gid_t cr_gid; - gid_t cr_groups[SVC_CRED_NGROUPS]; + struct group_info *cr_group_info; }; struct svc_rqst; /* forward decl */ diff -puN net/sunrpc/svcauth_unix.c~nfsd-NGROUPS-fixes net/sunrpc/svcauth_unix.c --- 25/net/sunrpc/svcauth_unix.c~nfsd-NGROUPS-fixes 2004-02-24 22:20:59.000000000 -0800 +++ 25-akpm/net/sunrpc/svcauth_unix.c 2004-02-24 22:20:59.000000000 -0800 @@ -357,7 +357,9 @@ svcauth_null_accept(struct svc_rqst *rqs /* Signal that mapping to nobody uid/gid is required */ rqstp->rq_cred.cr_uid = (uid_t) -1; rqstp->rq_cred.cr_gid = (gid_t) -1; - rqstp->rq_cred.cr_groups[0] = NOGROUP; + rqstp->rq_cred.cr_group_info = groups_alloc(0); + if (rqstp->rq_cred.cr_group_info == NULL) + return SVC_DROP; /* kmalloc failure - client must retry */ /* Put NULL verifier */ svc_putu32(resv, RPC_AUTH_NULL); @@ -424,6 +426,9 @@ svcauth_unix_accept(struct svc_rqst *rqs int rv=0; struct ip_map key, *ipm; + cred->cr_group_info = NULL; + rqstp->rq_client = NULL; + if ((len -= 3*4) < 0) return SVC_GARBAGE; @@ -440,13 +445,11 @@ svcauth_unix_accept(struct svc_rqst *rqs slen = ntohl(svc_getu32(argv)); /* gids length */ if (slen > 16 || (len -= (slen + 2)*4) < 0) goto badcred; + cred->cr_group_info = groups_alloc(slen); + if (cred->cr_group_info == NULL) + return SVC_DROP; for (i = 0; i < slen; i++) - if (i < SVC_CRED_NGROUPS) - cred->cr_groups[i] = ntohl(svc_getu32(argv)); - else - svc_getu32(argv); - if (i < SVC_CRED_NGROUPS) - cred->cr_groups[i] = NOGROUP; + GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv)); if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) { *authp = rpc_autherr_badverf; @@ -460,7 +463,6 @@ svcauth_unix_accept(struct svc_rqst *rqs ipm = ip_map_lookup(&key, 0); - rqstp->rq_client = NULL; if (ipm) switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { case -EAGAIN: @@ -501,6 +503,9 @@ svcauth_unix_release(struct svc_rqst *rq if (rqstp->rq_client) auth_domain_put(rqstp->rq_client); rqstp->rq_client = NULL; + if (rqstp->rq_cred.cr_group_info) + put_group_info(rqstp->rq_cred.cr_group_info); + rqstp->rq_cred.cr_group_info = NULL; return 0; } _