]> git.hungrycats.org Git - linux/commitdiff
[PATCH] knfsd: NGROUPS fixes
authorAndrew Morton <akpm@osdl.org>
Thu, 26 Feb 2004 14:45:06 +0000 (06:45 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 26 Feb 2004 14:45:06 +0000 (06:45 -0800)
From: Neil Brown <neilb@cse.unsw.edu.au>

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
fs/nfsd/nfs4state.c
fs/nfsd/nfsfh.c
include/linux/sunrpc/svcauth.h
net/sunrpc/svcauth_unix.c

index 5f630c60bb4dab61e74681e49029ee747b93adbe..bf38d343a285f942fb63fbd9810b18d72ad88fef 100644 (file)
 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, struct svc_export *exp)
        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;
 }
index a5710bbbe28e6bae56400185bd90e27c52c7ec00..c14f6d51101257dd7c1c48c932c18da0c0a53d05 100644 (file)
@@ -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, struct nfs4_client *source) {
 
 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
index 31c19821dda883a93f4e83875c6383879be9d5f3..aa4d31490e35238504d22dcfeeb02bfc74491211 100644 (file)
@@ -165,7 +165,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                }
 
                /* 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.
index 51c14facffe3060cc890eb6e8c09e8e7394600d3..ed0f6c91b61b381fc2271ce3fa82efba3f6e1243 100644 (file)
@@ -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 */
index 89255fd366f416d621bf9861a858740bea6f015b..77bcb661fbfa211ac2246a99297255efa2c3a287 100644 (file)
@@ -357,7 +357,9 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
        /* 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 *rqstp, u32 *authp)
        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 *rqstp, u32 *authp)
        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 *rqstp, u32 *authp)
 
        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 *rqstp)
        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;
 }