diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/lib/libc/rpc/netname.c ngroups/lib/libc/rpc/netname.c --- /usr/src/lib/libc/rpc/netname.c 2009-01-22 10:05:44.000000000 -0600 +++ ngroups/lib/libc/rpc/netname.c 2009-05-14 01:48:22.000000000 -0500 @@ -61,9 +61,6 @@ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif -#ifndef NGROUPS -#define NGROUPS 16 -#endif #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/lib/libc/rpc/netnamer.c ngroups/lib/libc/rpc/netnamer.c --- /usr/src/lib/libc/rpc/netnamer.c 2009-01-22 10:05:44.000000000 -0600 +++ ngroups/lib/libc/rpc/netnamer.c 2009-05-13 22:51:38.000000000 -0500 @@ -66,10 +66,6 @@ static int getnetid( char *, char * ); static int _getgroups( char *, gid_t * ); -#ifndef NGROUPS -#define NGROUPS 16 -#endif - /* * Convert network-name into unix credential */ @@ -104,7 +100,7 @@ return (0); } *gidp = (gid_t) atol(p); - for (gidlen = 0; gidlen < NGROUPS; gidlen++) { + for (gidlen = 0; gidlen < NGRPS; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) break; @@ -157,7 +153,7 @@ static int _getgroups(uname, groups) char *uname; - gid_t groups[NGROUPS]; + gid_t groups[NGRPS]; { gid_t ngroups = 0; struct group *grp; @@ -169,7 +165,7 @@ while ((grp = getgrent())) { for (i = 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups == NGROUPS) { + if (ngroups == NGRPS) { #ifdef DEBUG fprintf(stderr, "initgroups: %s is in too many groups\n", uname); diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/contrib/pf/net/pf.c ngroups/sys/contrib/pf/net/pf.c --- /usr/src/sys/contrib/pf/net/pf.c 2009-06-05 15:33:53.000000000 -0500 +++ ngroups/sys/contrib/pf/net/pf.c 2009-06-05 16:02:32.000000000 -0500 @@ -2945,7 +2945,7 @@ if (inp_arg != NULL) { INP_LOCK_ASSERT(inp_arg); pd->lookup.uid = inp_arg->inp_cred->cr_uid; - pd->lookup.gid = inp_arg->inp_cred->cr_groups[0]; + pd->lookup.gid = inp_arg->inp_cred->cr_gid; return (1); } #endif @@ -3043,7 +3043,7 @@ } #ifdef __FreeBSD__ pd->lookup.uid = inp->inp_cred->cr_uid; - pd->lookup.gid = inp->inp_cred->cr_groups[0]; + pd->lookup.gid = inp->inp_cred->cr_gid; INP_INFO_RUNLOCK(pi); #else pd->lookup.uid = inp->inp_socket->so_euid; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/nfs/nfs_commonport.c ngroups/sys/fs/nfs/nfs_commonport.c --- /usr/src/sys/fs/nfs/nfs_commonport.c 2009-05-29 12:48:03.000000000 -0500 +++ ngroups/sys/fs/nfs/nfs_commonport.c 2009-06-05 15:33:54.000000000 -0500 @@ -220,14 +220,9 @@ void newnfs_copycred(struct nfscred *nfscr, struct ucred *cr) { - int ngroups, i; cr->cr_uid = nfscr->nfsc_uid; - ngroups = (nfscr->nfsc_ngroups < NGROUPS) ? - nfscr->nfsc_ngroups : NGROUPS; - for (i = 0; i < ngroups; i++) - cr->cr_groups[i] = nfscr->nfsc_groups[i]; - cr->cr_ngroups = ngroups; + crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); } /* @@ -295,15 +290,13 @@ /* * Set the credentials to refer to root. - * If only the various BSDen could agree on whether cr_gid is a separate - * field or cr_groups[0]... */ void newnfs_setroot(struct ucred *cred) { cred->cr_uid = 0; - cred->cr_groups[0] = 0; + cred->cr_gid = 0; cred->cr_ngroups = 1; } diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/nfsclient/nfs_clport.c ngroups/sys/fs/nfsclient/nfs_clport.c --- /usr/src/sys/fs/nfsclient/nfs_clport.c 2009-05-29 12:48:03.000000000 -0500 +++ ngroups/sys/fs/nfsclient/nfs_clport.c 2009-06-05 15:33:54.000000000 -0500 @@ -976,14 +976,12 @@ void newnfs_copyincred(struct ucred *cr, struct nfscred *nfscr) { - int ngroups, i; + int i; nfscr->nfsc_uid = cr->cr_uid; - ngroups = (cr->cr_ngroups > NGROUPS) ? NGROUPS : - cr->cr_ngroups; - for (i = 0; i < ngroups; i++) + nfscr->nfsc_ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); + for (i = 0; i < nfscr->nfsc_ngroups; i++) nfscr->nfsc_groups[i] = cr->cr_groups[i]; - nfscr->nfsc_ngroups = ngroups; } diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/nfsserver/nfs_nfsdport.c ngroups/sys/fs/nfsserver/nfs_nfsdport.c --- /usr/src/sys/fs/nfsserver/nfs_nfsdport.c 2009-06-05 15:33:50.000000000 -0500 +++ ngroups/sys/fs/nfsserver/nfs_nfsdport.c 2009-06-05 16:02:29.000000000 -0500 @@ -2360,7 +2360,6 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, struct ucred *credanon) { - int i; int error = 0; /* @@ -2403,9 +2402,8 @@ (nd->nd_flag & ND_AUTHNONE))) { nd->nd_cred->cr_uid = credanon->cr_uid; nd->nd_cred->cr_gid = credanon->cr_gid; - for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - nd->nd_cred->cr_groups[i] = credanon->cr_groups[i]; - nd->nd_cred->cr_ngroups = i; + crsetgroups(nd->nd_cred, credanon->cr_ngroups, + credanon->cr_groups); } return (0); } diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/nfsserver/nfs_nfsdstate.c ngroups/sys/fs/nfsserver/nfs_nfsdstate.c --- /usr/src/sys/fs/nfsserver/nfs_nfsdstate.c 2009-05-29 12:48:03.000000000 -0500 +++ ngroups/sys/fs/nfsserver/nfs_nfsdstate.c 2009-06-05 15:33:54.000000000 -0500 @@ -3577,7 +3577,6 @@ nd->nd_repstat = 0; cred->cr_uid = clp->lc_uid; cred->cr_gid = clp->lc_gid; - cred->cr_groups[0] = clp->lc_gid; callback = clp->lc_callback; NFSUNLOCKSTATE(); cred->cr_ngroups = 1; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/portalfs/portal.h ngroups/sys/fs/portalfs/portal.h --- /usr/src/sys/fs/portalfs/portal.h 2009-01-22 10:06:01.000000000 -0600 +++ ngroups/sys/fs/portalfs/portal.h 2009-06-05 15:33:54.000000000 -0500 @@ -43,7 +43,7 @@ int pcr_flag; /* File open mode */ uid_t pcr_uid; /* From ucred */ short pcr_ngroups; /* From ucred */ - gid_t pcr_groups[NGROUPS]; /* From ucred */ + gid_t pcr_groups[XU_NGROUPS]; /* From ucred */ }; #ifdef _KERNEL diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/portalfs/portal_vnops.c ngroups/sys/fs/portalfs/portal_vnops.c --- /usr/src/sys/fs/portalfs/portal_vnops.c 2009-01-22 10:06:01.000000000 -0600 +++ ngroups/sys/fs/portalfs/portal_vnops.c 2009-06-05 15:33:54.000000000 -0500 @@ -311,8 +311,9 @@ pcred.pcr_flag = ap->a_mode; pcred.pcr_uid = ap->a_cred->cr_uid; - pcred.pcr_ngroups = ap->a_cred->cr_ngroups; - bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); + pcred.pcr_ngroups = MIN(ap->a_cred->cr_ngroups, XU_NGROUPS); + bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, + pcred.pcr_ngroups * sizeof(gid_t)); aiov[0].iov_base = (caddr_t) &pcred; aiov[0].iov_len = sizeof(pcred); aiov[1].iov_base = pt->pt_arg; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/fs/unionfs/union_vnops.c ngroups/sys/fs/unionfs/union_vnops.c --- /usr/src/sys/fs/unionfs/union_vnops.c 2009-04-12 15:26:52.000000000 -0500 +++ ngroups/sys/fs/unionfs/union_vnops.c 2009-06-05 15:33:54.000000000 -0500 @@ -638,7 +638,6 @@ uid_t uid; /* upper side vnode's uid */ gid_t gid; /* upper side vnode's gid */ u_short vmode; /* upper side vnode's mode */ - gid_t *gp; u_short mask; mask = 0; @@ -659,17 +658,14 @@ /* check group */ count = 0; - gp = cred->cr_groups; - for (; count < cred->cr_ngroups; count++, gp++) { - if (gid == *gp) { - if (accmode & VEXEC) - mask |= S_IXGRP; - if (accmode & VREAD) - mask |= S_IRGRP; - if (accmode & VWRITE) - mask |= S_IWGRP; - return ((vmode & mask) == mask ? 0 : EACCES); - } + if (groupmember(gid, cred)) { + if (accmode & VEXEC) + mask |= S_IXGRP; + if (accmode & VREAD) + mask |= S_IRGRP; + if (accmode & VWRITE) + mask |= S_IWGRP; + return ((vmode & mask) == mask ? 0 : EACCES); } /* check other */ diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h ngroups/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h --- /usr/src/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h 2009-02-28 13:28:12.000000000 -0600 +++ ngroups/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h 2009-06-05 15:33:54.000000000 -0500 @@ -163,7 +163,7 @@ * Cedentials manipulation. */ #define current_fsuid(credp) (credp)->cr_uid -#define current_fsgid(credp) (credp)->cr_groups[0] +#define current_fsgid(credp) (credp)->cr_gid #define PAGE_CACHE_SIZE PAGE_SIZE diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/gnu/fs/xfs/xfs_inode.c ngroups/sys/gnu/fs/xfs/xfs_inode.c --- /usr/src/sys/gnu/fs/xfs/xfs_inode.c 2009-01-21 12:45:49.000000000 -0600 +++ ngroups/sys/gnu/fs/xfs/xfs_inode.c 2009-06-05 15:33:54.000000000 -0500 @@ -1124,7 +1124,7 @@ ip->i_d.di_nlink = nlink; ASSERT(ip->i_d.di_nlink == nlink); ip->i_d.di_uid = curthread->td_ucred->cr_uid; - ip->i_d.di_gid = curthread->td_ucred->cr_groups[0]; + ip->i_d.di_gid = curthread->td_ucred->cr_gid; ip->i_d.di_projid = prid; memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/gnu/fs/xfs/xfs_vnodeops.c ngroups/sys/gnu/fs/xfs/xfs_vnodeops.c --- /usr/src/sys/gnu/fs/xfs/xfs_vnodeops.c 2009-01-21 12:45:49.000000000 -0600 +++ ngroups/sys/gnu/fs/xfs/xfs_vnodeops.c 2009-06-05 15:33:54.000000000 -0500 @@ -3379,7 +3379,7 @@ */ error = XFS_QM_DQVOPALLOC(mp, dp, current->td_ucred->cr_uid, - current->td_ucred->cr_groups[0], + current->td_ucred->cr_gid, prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) Only in /usr/src/sys/i386/ibcs2: ibcs2_misc.c.orig Only in /usr/src/sys/kern: kern_exec.c.orig Only in /usr/src/sys/kern: kern_proc.c.orig diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/kern/kern_prot.c ngroups/sys/kern/kern_prot.c --- /usr/src/sys/kern/kern_prot.c 2009-06-05 15:33:50.000000000 -0500 +++ ngroups/sys/kern/kern_prot.c 2009-06-05 16:02:28.000000000 -0500 @@ -82,6 +82,9 @@ SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); +static __inline void crsetgroups_locked(struct ucred *cr, int ngrp, + gid_t *groups); + #ifndef _SYS_SYSPROTO_H_ struct getpid_args { int dummy; @@ -243,16 +246,11 @@ td->td_retval[0] = td->td_ucred->cr_rgid; #if defined(COMPAT_43) - td->td_retval[1] = td->td_ucred->cr_groups[0]; + td->td_retval[1] = td->td_ucred->cr_gid; #endif return (0); } -/* - * Get effective group ID. The "egid" is groups[0], and could be obtained - * via getgroups. This syscall exists because it is somewhat painful to do - * correctly in a library function. - */ #ifndef _SYS_SYSPROTO_H_ struct getegid_args { int dummy; @@ -263,7 +261,7 @@ getegid(struct thread *td, struct getegid_args *uap) { - td->td_retval[0] = td->td_ucred->cr_groups[0]; + td->td_retval[0] = td->td_ucred->cr_gid; return (0); } @@ -679,7 +677,7 @@ gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ + gid != oldcred->cr_gid && /* allow setgid(getegid()) */ #endif (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) goto fail; @@ -691,7 +689,7 @@ */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ - gid == oldcred->cr_groups[0] || + gid == oldcred->cr_gid || #endif /* We are using privs. */ priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0) @@ -720,7 +718,7 @@ * In all cases permitted cases, we are changing the egid. * Copy credentials so other references do not see our changes. */ - if (oldcred->cr_groups[0] != gid) { + if (oldcred->cr_gid != gid) { change_egid(newcred, gid); setsugid(p); } @@ -766,7 +764,7 @@ (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) goto fail; - if (oldcred->cr_groups[0] != egid) { + if (oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -811,7 +809,6 @@ { struct proc *p = td->td_proc; struct ucred *newcred, *oldcred; - int newgroups; int error; if (ngrp > NGROUPS) @@ -820,16 +817,7 @@ newcred = crget(); crextend(newcred, ngrp); PROC_LOCK(p); - oldcred = p->p_ucred; - newgroups = MAX(oldcred->cr_agroups, ngrp); - while (newcred->cr_agroups < newgroups) { - PROC_UNLOCK(p); - crextend(newcred, newgroups); - PROC_LOCK(p); - oldcred = p->p_ucred; - newgroups = MAX(oldcred->cr_agroups, ngrp); - } - + oldcred = crcopysafe(p, newcred); #ifdef MAC error = mac_cred_check_setgroups(oldcred, ngrp, groups); @@ -841,7 +829,6 @@ if (error) goto fail; - crcopy(newcred, oldcred); if (ngrp < 1) { /* * setgroups(0, NULL) is a legitimate way of clearing the @@ -851,8 +838,7 @@ */ newcred->cr_ngroups = 1; } else { - bcopy(groups, newcred->cr_groups, ngrp * sizeof(gid_t)); - newcred->cr_ngroups = ngrp; + crsetgroups_locked(newcred, ngrp, groups); } setsugid(p); p->p_ucred = newcred; @@ -964,12 +950,12 @@ if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && rgid != oldcred->cr_svgid) || - (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && + (egid != (gid_t)-1 && egid != oldcred->cr_gid && egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) goto fail; - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + if (egid != (gid_t)-1 && oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -977,9 +963,9 @@ change_rgid(newcred, rgid); setsugid(p); } - if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && - newcred->cr_svgid != newcred->cr_groups[0]) { - change_svgid(newcred, newcred->cr_groups[0]); + if ((rgid != (gid_t)-1 || newcred->cr_gid != newcred->cr_rgid) && + newcred->cr_svgid != newcred->cr_gid) { + change_svgid(newcred, newcred->cr_gid); setsugid(p); } p->p_ucred = newcred; @@ -1110,17 +1096,17 @@ if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && rgid != oldcred->cr_svgid && - rgid != oldcred->cr_groups[0]) || + rgid != oldcred->cr_gid) || (egid != (gid_t)-1 && egid != oldcred->cr_rgid && egid != oldcred->cr_svgid && - egid != oldcred->cr_groups[0]) || + egid != oldcred->cr_gid) || (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && sgid != oldcred->cr_svgid && - sgid != oldcred->cr_groups[0])) && + sgid != oldcred->cr_gid)) && (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) goto fail; - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + if (egid != (gid_t)-1 && oldcred->cr_gid != egid) { change_egid(newcred, egid); setsugid(p); } @@ -1189,8 +1175,8 @@ error1 = copyout(&cred->cr_rgid, uap->rgid, sizeof(cred->cr_rgid)); if (uap->egid) - error2 = copyout(&cred->cr_groups[0], - uap->egid, sizeof(cred->cr_groups[0])); + error2 = copyout(&cred->cr_gid, + uap->egid, sizeof(cred->cr_gid)); if (uap->sgid) error3 = copyout(&cred->cr_svgid, uap->sgid, sizeof(cred->cr_svgid)); @@ -1911,7 +1897,7 @@ ngroups = min(cr->cr_ngroups, XU_NGROUPS); xcr->cr_ngroups = ngroups; bcopy(cr->cr_groups, xcr->cr_groups, - ngroups * sizeof(cr->cr_groups[0])); + ngroups * sizeof(*cr->cr_groups)); } /* @@ -1969,6 +1955,8 @@ /* * We extend by 2 each time since we're using a power of two * allocator. + * XXX: it probably makes more sense to right-size the + * allocation if we need more than a page. */ if (cr->cr_agroups) cnt = cr->cr_agroups * 2; @@ -1987,6 +1975,36 @@ } /* + * Copy groups in to a credential, preserving any necessicary invariants + * (i.e. sorting in the future). crextend() must have been called + * before hand to ensure sufficient space is available. If + */ +static inline void +crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) +{ + + KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); + + bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); + cr->cr_ngroups = ngrp; +} + +/* + * Copy groups in to a credential after expanding it if required. + * Truncate the list to NGROUPS if it is too large. + */ +void +crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) +{ + + if (ngrp > NGROUPS) + ngrp = NGROUPS; + + crextend(cr, ngrp); + crsetgroups_locked(cr, ngrp, groups); +} + +/* * Get login name, if available. */ #ifndef _SYS_SYSPROTO_H_ @@ -2083,7 +2101,7 @@ change_egid(struct ucred *newcred, gid_t egid) { - newcred->cr_groups[0] = egid; + newcred->cr_gid = egid; } /*- Only in /usr/src/sys/kern: kern_prot.c.orig diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/kern/vfs_export.c ngroups/sys/kern/vfs_export.c --- /usr/src/sys/kern/vfs_export.c 2009-05-29 12:48:02.000000000 -0500 +++ ngroups/sys/kern/vfs_export.c 2009-06-05 15:33:54.000000000 -0500 @@ -120,9 +120,8 @@ np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups; - bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups, - sizeof(np->netc_anon->cr_groups)); + crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, + argp->ex_anon.cr_groups); np->netc_numsecflavors = argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); @@ -205,9 +204,8 @@ np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups; - bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups, - sizeof(np->netc_anon->cr_groups)); + crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, + np->netc_anon->cr_groups); np->netc_numsecflavors = argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/kern/vfs_syscalls.c ngroups/sys/kern/vfs_syscalls.c --- /usr/src/sys/kern/vfs_syscalls.c 2009-06-05 15:33:50.000000000 -0500 +++ ngroups/sys/kern/vfs_syscalls.c 2009-06-05 16:02:28.000000000 -0500 @@ -2128,7 +2128,7 @@ cred = td->td_ucred; tmpcred = crdup(cred); tmpcred->cr_uid = cred->cr_ruid; - tmpcred->cr_groups[0] = cred->cr_rgid; + tmpcred->cr_gid = cred->cr_rgid; td->td_ucred = tmpcred; } else cred = tmpcred = td->td_ucred; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/netinet/ipfw/ip_fw2.c ngroups/sys/netinet/ipfw/ip_fw2.c --- /usr/src/sys/netinet/ipfw/ip_fw2.c 2009-06-05 15:33:50.000000000 -0500 +++ ngroups/sys/netinet/ipfw/ip_fw2.c 2009-06-05 16:02:28.000000000 -0500 @@ -139,8 +139,9 @@ * the user specified UID/GID based constraints in * a firewall rule. */ +#define FW_NGROUPS 16 struct ip_fw_ugid { - gid_t fw_groups[NGROUPS]; + gid_t fw_groups[FW_NGROUPS]; /* XXX: should be dynamic */ int fw_ngroups; uid_t fw_uid; int fw_prid; @@ -2016,8 +2017,8 @@ cr = inp->inp_cred; ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1; ugp->fw_uid = cr->cr_uid; - ugp->fw_ngroups = cr->cr_ngroups; - bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups)); + ugp->fw_ngroups = MIN(cr->cr_ngroups, FW_NGROUPS); + bcopy(cr->cr_groups, ugp->fw_groups, sizeof(gid_t) * ugp->fw_ngroups); } static int diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/netncp/ncp_conn.c ngroups/sys/netncp/ncp_conn.c --- /usr/src/sys/netncp/ncp_conn.c 2009-01-22 10:06:17.000000000 -0600 +++ ngroups/sys/netncp/ncp_conn.c 2009-06-05 15:33:54.000000000 -0500 @@ -249,7 +249,7 @@ ncp->connid = 0xFFFF; ncp->li = *cap; ncp->nc_group = (cap->group != NCP_DEFAULT_GROUP) ? - cap->group : cred->cr_groups[0]; + cap->group : cred->cr_gid; if (cap->retry_count == 0) ncp->li.retry_count = NCP_RETRY_COUNT; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/netsmb/smb_conn.c ngroups/sys/netsmb/smb_conn.c --- /usr/src/sys/netsmb/smb_conn.c 2009-01-22 10:06:17.000000000 -0600 +++ ngroups/sys/netsmb/smb_conn.c 2009-06-05 15:33:54.000000000 -0500 @@ -416,7 +416,7 @@ if (uid == SMBM_ANY_OWNER) uid = realuid; if (gid == SMBM_ANY_GROUP) - gid = cred->cr_groups[0]; + gid = cred->cr_gid; vcp->vc_uid = uid; vcp->vc_grp = gid; @@ -714,7 +714,7 @@ if (uid == SMBM_ANY_OWNER) uid = realuid; if (gid == SMBM_ANY_GROUP) - gid = cred->cr_groups[0]; + gid = cred->cr_gid; ssp = smb_zmalloc(sizeof(*ssp), M_SMBCONN, M_WAITOK); smb_co_init(SSTOCP(ssp), SMBL_SHARE, "smbss ilock", "smbss"); ssp->obj.co_free = smb_share_free; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/nfsclient/nfs_subs.c ngroups/sys/nfsclient/nfs_subs.c --- /usr/src/sys/nfsclient/nfs_subs.c 2009-05-29 12:48:02.000000000 -0500 +++ ngroups/sys/nfsclient/nfs_subs.c 2009-06-05 15:33:54.000000000 -0500 @@ -253,7 +253,7 @@ *tl++ = 0; /* stamp ?? */ *tl++ = 0; /* NULL hostname */ *tl++ = txdr_unsigned(cr->cr_uid); - *tl++ = txdr_unsigned(cr->cr_groups[0]); + *tl++ = txdr_unsigned(cr->cr_gid); grpsiz = (auth_len >> 2) - 5; *tl++ = txdr_unsigned(grpsiz); for (i = 1; i <= grpsiz; i++) diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/nfsserver/nfs_srvsock.c ngroups/sys/nfsserver/nfs_srvsock.c --- /usr/src/sys/nfsserver/nfs_srvsock.c 2009-06-05 15:33:51.000000000 -0500 +++ ngroups/sys/nfsserver/nfs_srvsock.c 2009-06-05 16:02:29.000000000 -0500 @@ -358,7 +358,7 @@ tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED); nd->nd_cr->cr_uid = nd->nd_cr->cr_ruid = nd->nd_cr->cr_svuid = fxdr_unsigned(uid_t, *tl++); - nd->nd_cr->cr_groups[0] = nd->nd_cr->cr_rgid = + nd->nd_cr->cr_gid = nd->nd_cr->cr_rgid = nd->nd_cr->cr_svgid = fxdr_unsigned(gid_t, *tl++); #ifdef MAC mac_cred_associate_nfsd(nd->nd_cr); @@ -374,7 +374,7 @@ nd->nd_cr->cr_groups[i] = fxdr_unsigned(gid_t, *tl++); else tl++; - nd->nd_cr->cr_ngroups = (len >= XU_NGROUPS) ? XU_NGROUPS : (len + 1); + nd->nd_cr->cr_ngroups = MIN(XU_NGROUPS, len + 1); if (nd->nd_cr->cr_ngroups > 1) nfsrvw_sort(nd->nd_cr->cr_groups, nd->nd_cr->cr_ngroups); len = fxdr_unsigned(int, *++tl); Only in /usr/src/sys/nfsserver: nfs_srvsock.c.orig diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/nfsserver/nfs_srvsubs.c ngroups/sys/nfsserver/nfs_srvsubs.c --- /usr/src/sys/nfsserver/nfs_srvsubs.c 2009-05-29 12:48:04.000000000 -0500 +++ ngroups/sys/nfsserver/nfs_srvsubs.c 2009-06-05 15:33:54.000000000 -0500 @@ -1181,9 +1181,7 @@ cred = nfsd->nd_cr; if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { cred->cr_uid = credanon->cr_uid; - for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - cred->cr_groups[i] = credanon->cr_groups[i]; - cred->cr_ngroups = i; + crsetgroups(cred, credanon->cr_ngroups, credanon->cr_groups); } if (exflags & MNT_EXRDONLY) *rdonlyp = 1; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/rpc/authunix_prot.c ngroups/sys/rpc/authunix_prot.c --- /usr/src/sys/rpc/authunix_prot.c 2009-06-05 15:33:49.000000000 -0500 +++ ngroups/sys/rpc/authunix_prot.c 2009-06-05 16:02:28.000000000 -0500 @@ -98,7 +98,7 @@ if (!xdr_uint32_t(xdrs, &cred->cr_uid)) return (FALSE); - if (!xdr_uint32_t(xdrs, &cred->cr_groups[0])) + if (!xdr_uint32_t(xdrs, &cred->cr_gid)) return (FALSE); if (xdrs->x_op == XDR_ENCODE) { diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c ngroups/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- /usr/src/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-01-22 10:05:57.000000000 -0600 +++ ngroups/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-05 15:33:54.000000000 -0500 @@ -447,11 +447,7 @@ cr = client->cl_cred = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; cr->cr_rgid = cr->cr_svgid = uc->gid; - cr->cr_ngroups = uc->gidlen; - if (cr->cr_ngroups > NGROUPS) - cr->cr_ngroups = NGROUPS; - for (i = 0; i < cr->cr_ngroups; i++) - cr->cr_groups[i] = uc->gidlist[i]; + crsetgroups(cr, uc->gidlen, uc->gidlist); *crp = crhold(cr); return (TRUE); diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/rpc/svc_auth.c ngroups/sys/rpc/svc_auth.c --- /usr/src/sys/rpc/svc_auth.c 2009-01-22 10:05:57.000000000 -0600 +++ ngroups/sys/rpc/svc_auth.c 2009-06-05 15:33:54.000000000 -0500 @@ -165,7 +165,7 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int *flavorp) { struct ucred *cr = NULL; - int flavor, i; + int flavor; struct xucred *xcr; flavor = rqst->rq_cred.oa_flavor; @@ -177,10 +177,8 @@ xcr = (struct xucred *) rqst->rq_clntcred; cr = crget(); cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xcr->cr_uid; - cr->cr_ngroups = xcr->cr_ngroups; - for (i = 0; i < xcr->cr_ngroups; i++) - cr->cr_groups[i] = xcr->cr_groups[i]; - cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; + crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); + cr->cr_rgid = cr->cr_svgid = cr->cr_gid; *crp = cr; return (TRUE); diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/rpc/svc_auth_unix.c ngroups/sys/rpc/svc_auth_unix.c --- /usr/src/sys/rpc/svc_auth_unix.c 2009-01-22 10:05:57.000000000 -0600 +++ ngroups/sys/rpc/svc_auth_unix.c 2009-06-05 15:33:54.000000000 -0500 @@ -88,20 +88,20 @@ str_len = RNDUP(str_len); buf += str_len / sizeof (int32_t); xcr->cr_uid = IXDR_GET_UINT32(buf); - xcr->cr_groups[0] = IXDR_GET_UINT32(buf); + xcr->cr_gid = IXDR_GET_UINT32(buf); gid_len = (size_t)IXDR_GET_UINT32(buf); if (gid_len > NGRPS) { stat = AUTH_BADCRED; goto done; } for (i = 0; i < gid_len; i++) { - if (i + 1 < NGROUPS) + if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] = IXDR_GET_INT32(buf); else buf++; } - if (gid_len + 1 > NGROUPS) - xcr->cr_ngroups = NGROUPS; + if (gid_len + 1 > XU_NGROUPS) + xcr->cr_ngroups = XU_NGROUPS; else xcr->cr_ngroups = gid_len + 1; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/security/audit/audit.c ngroups/sys/security/audit/audit.c --- /usr/src/sys/security/audit/audit.c 2009-04-24 10:41:08.000000000 -0500 +++ ngroups/sys/security/audit/audit.c 2009-06-05 15:33:54.000000000 -0500 @@ -224,7 +224,7 @@ cru2x(cred, &ar->k_ar.ar_subj_cred); ar->k_ar.ar_subj_ruid = cred->cr_ruid; ar->k_ar.ar_subj_rgid = cred->cr_rgid; - ar->k_ar.ar_subj_egid = cred->cr_groups[0]; + ar->k_ar.ar_subj_egid = cred->cr_gid; ar->k_ar.ar_subj_auid = cred->cr_audit.ai_auid; ar->k_ar.ar_subj_asid = cred->cr_audit.ai_asid; ar->k_ar.ar_subj_pid = td->td_proc->p_pid; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/security/audit/audit_arg.c ngroups/sys/security/audit/audit_arg.c --- /usr/src/sys/security/audit/audit_arg.c 2009-01-22 10:06:21.000000000 -0600 +++ ngroups/sys/security/audit/audit_arg.c 2009-06-05 15:33:54.000000000 -0500 @@ -369,7 +369,7 @@ cred = p->p_ucred; ar->k_ar.ar_arg_auid = cred->cr_audit.ai_auid; ar->k_ar.ar_arg_euid = cred->cr_uid; - ar->k_ar.ar_arg_egid = cred->cr_groups[0]; + ar->k_ar.ar_arg_egid = cred->cr_gid; ar->k_ar.ar_arg_ruid = cred->cr_ruid; ar->k_ar.ar_arg_rgid = cred->cr_rgid; ar->k_ar.ar_arg_asid = cred->cr_audit.ai_asid; diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/sys/syslimits.h ngroups/sys/sys/syslimits.h --- /usr/src/sys/sys/syslimits.h 2009-01-22 10:06:22.000000000 -0600 +++ ngroups/sys/sys/syslimits.h 2009-06-05 15:34:15.000000000 -0500 @@ -54,7 +54,7 @@ #define MAX_CANON 255 /* max bytes in term canon input line */ #define MAX_INPUT 255 /* max bytes in terminal input */ #define NAME_MAX 255 /* max bytes in a file name */ -#define NGROUPS_MAX 16 /* max supplemental group id's */ +#define NGROUPS_MAX 32767 /* max supplemental group id's */ #ifndef OPEN_MAX #define OPEN_MAX 64 /* max open files per process */ #endif diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/sys/ucred.h ngroups/sys/sys/ucred.h --- /usr/src/sys/sys/ucred.h 2009-06-05 15:33:54.000000000 -0500 +++ ngroups/sys/sys/ucred.h 2009-06-05 16:02:34.000000000 -0500 @@ -48,7 +48,7 @@ uid_t cr_uid; /* effective user id */ uid_t cr_ruid; /* real user id */ uid_t cr_svuid; /* saved user id */ - short cr_ngroups; /* number of groups */ + int cr_ngroups; /* number of groups */ gid_t cr_rgid; /* real group id */ gid_t cr_svgid; /* saved group id */ struct uidinfo *cr_uidinfo; /* per euid resource consumption */ @@ -61,7 +61,7 @@ struct label *cr_label; /* MAC label */ struct auditinfo_addr cr_audit; /* Audit properties. */ gid_t *cr_groups; /* groups */ - short cr_agroups; /* Available groups */ + int cr_agroups; /* Available groups */ }; #define NOCRED ((struct ucred *)0) /* no credential available */ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ @@ -77,11 +77,9 @@ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ gid_t cr_groups[XU_NGROUPS]; /* groups */ + void *_cr_unused1; /* compatibility with old ucred */ }; -#define XUCRED_VERSION 2 - -#define XUCRED_SIZE(n) \ - (sizeof(struct xucred) + (MAX((n)-XU_NGROUPS, 0) * sizeof(gid_t))) +#define XUCRED_VERSION 0 /* This can be used for both ucred and xucred structures. */ #define cr_gid cr_groups[0] @@ -97,7 +95,7 @@ void change_svgid(struct ucred *newcred, gid_t svgid); void change_svuid(struct ucred *newcred, uid_t svuid); void crcopy(struct ucred *dest, struct ucred *src); -struct ucred *crcopysafe(struct proc *, struct ucred *); +struct ucred *crcopysafe(struct proc *p, struct ucred *cr); struct ucred *crdup(struct ucred *cr); void cred_update_thread(struct thread *td); void crfree(struct ucred *cr); @@ -106,6 +104,7 @@ int crshared(struct ucred *cr); void cru2x(struct ucred *cr, struct xucred *xcr); void crextend(struct ucred *cr, int n); +void crsetgroups(struct ucred *cr, int n, gid_t *groups); int groupmember(gid_t gid, struct ucred *cred); #endif /* _KERNEL */ Only in /usr/src/sys/sys: ucred.h.orig Only in /usr/src/sys/sys: user.h.diff Only in /usr/src/sys/sys: user.h.orig Only in /usr/src/sys/sys: user.h.rej.orig diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/sys/ufs/ufs/ufs_vnops.c ngroups/sys/ufs/ufs/ufs_vnops.c --- /usr/src/sys/ufs/ufs/ufs_vnops.c 2009-06-05 15:33:49.000000000 -0500 +++ ngroups/sys/ufs/ufs/ufs_vnops.c 2009-06-05 16:02:28.000000000 -0500 @@ -1475,7 +1475,7 @@ refcount_init(&ucred.cr_ref, 1); ucred.cr_uid = ip->i_uid; ucred.cr_ngroups = 1; - ucred.cr_groups[0] = dp->i_gid; + ucred.cr_gid = dp->i_gid; ucp = &ucred; } #endif @@ -2266,6 +2266,7 @@ { #ifdef QUOTA struct ucred ucred, *ucp; + gid_t ucred_group; ucp = cnp->cn_cred; #endif /* @@ -2292,7 +2293,8 @@ refcount_init(&ucred.cr_ref, 1); ucred.cr_uid = ip->i_uid; ucred.cr_ngroups = 1; - ucred.cr_groups[0] = pdir->i_gid; + ucred.cr_groups = &ucred_group; + ucred.cr_gid = pdir->i_gid; ucp = &ucred; #endif } else { diff -ru --exclude='.glimpse*' --exclude=.svn --exclude=compile --ignore-matching='$FreeBSD' /usr/src/usr.sbin/mountd/mountd.c ngroups/usr.sbin/mountd/mountd.c --- /usr/src/usr.sbin/mountd/mountd.c 2009-05-29 12:47:59.000000000 -0500 +++ ngroups/usr.sbin/mountd/mountd.c 2009-05-28 17:11:49.000000000 -0500 @@ -174,7 +174,7 @@ int do_mount(struct exportlist *, struct grouplist *, int, struct xucred *, char *, int, struct statfs *); int do_opt(char **, char **, struct exportlist *, struct grouplist *, - int *, int *, struct xucred **); + int *, int *, struct xucred *); struct exportlist *ex_search(fsid_t *); struct exportlist *get_exp(void); void free_dir(struct dirlist *); @@ -196,7 +196,7 @@ void mntsrv(struct svc_req *, SVCXPRT *); void nextfield(char **, char **); void out_of_mem(void); -void parsecred(char *, struct xucred **); +void parsecred(char *, struct xucred *); int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); void *sa_rawaddr(struct sockaddr *sa, int *nbytes); int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, @@ -221,6 +221,7 @@ (uid_t)-2, 1, { (gid_t)-2 }, + NULL }; int force_v2 = 0; int resvport_only = 1; @@ -1167,7 +1168,7 @@ struct exportlist **epp; struct dirlist *dirhead; struct statfs fsb; - struct xucred *anon; + struct xucred anon; char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; int len, has_host, exflags, got_nondir, dirplen, netgrp; @@ -1185,7 +1186,7 @@ * Set defaults. */ has_host = FALSE; - anon = &def_anon; + anon = def_anon; exflags = MNT_EXPORTED; got_nondir = 0; opt_flags = 0; @@ -1403,7 +1404,7 @@ */ grp = tgrp; do { - if (do_mount(ep, grp, exflags, anon, dirp, dirplen, + if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, &fsb)) { getexp_err(ep, tgrp); goto nextline; @@ -1956,7 +1957,7 @@ struct grouplist *grp; int *has_hostp; int *exflagsp; - struct xucred **cr; + struct xucred *cr; { char *cpoptarg, *cpoptend; char *cp, *endcp, *cpopt, savedc, savedc2; @@ -2420,33 +2421,6 @@ return (ret); } -static void -xcr_grow(struct xucred **cr, int *cr_ngroups, int desired_groups) -{ - struct xucred *in = *cr, *out; - int n; - - if (in && *cr_ngroups > desired_groups) - return; - - n = MAX(XU_NGROUPS, *cr_ngroups); - while (n < desired_groups) - n *= 2; - - out = malloc(XUCRED_SIZE(n)); - if (out == NULL) - out_of_mem(); - - if (in) { - memcpy(out, in, XUCRED_SIZE(*cr_ngroups)); - if (in != &def_anon) - free(in); - } - - *cr = out; - *cr_ngroups = n; -} - /* * Translate a net address. * @@ -2654,20 +2628,18 @@ * Parse a description of a credential. */ void -parsecred(namelist, cr_out) +parsecred(namelist, cr) char *namelist; - struct xucred **cr_out; + struct xucred *cr; { char *name; + int cnt; char *names; struct passwd *pw; struct group *gr; + gid_t groups[NGRPS + 1]; int ngroups; - struct xucred *cr = NULL; - int cr_ngroups = 0; - int error; - xcr_grow(&cr, &cr_ngroups, 0); cr->cr_version = XUCRED_VERSION; /* * Set up the unprivileged user. @@ -2690,20 +2662,20 @@ if (names == NULL) { if (pw == NULL) { syslog(LOG_ERR, "unknown user: %s", name); - goto out; + return; } cr->cr_uid = pw->pw_uid; - for (;;) { - ngroups = cr_ngroups; - error = getgrouplist(pw->pw_name, pw->pw_gid, - cr->cr_groups, &ngroups); - if (!error) - break; - xcr_grow(&cr, &cr_ngroups, ngroups); - } - cr->cr_ngroups = ngroups; - - goto out; + ngroups = NGRPS + 1; + if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) + syslog(LOG_ERR, "too many groups"); + /* + * Compress out duplicate. + */ + cr->cr_ngroups = ngroups - 1; + cr->cr_groups[0] = groups[0]; + for (cnt = 2; cnt < ngroups; cnt++) + cr->cr_groups[cnt - 1] = groups[cnt]; + return; } /* * Explicit credential specified as a colon separated list: @@ -2715,11 +2687,10 @@ cr->cr_uid = atoi(name); else { syslog(LOG_ERR, "unknown user: %s", name); - goto out; + return; } cr->cr_ngroups = 0; - while (names != NULL && *names != '\0') { - xcr_grow(&cr, &cr_ngroups, cr->cr_ngroups + 1); + while (names != NULL && *names != '\0' && cr->cr_ngroups < NGRPS) { name = strsep(&names, ":"); if (isdigit(*name) || *name == '-') { cr->cr_groups[cr->cr_ngroups++] = atoi(name); @@ -2731,9 +2702,8 @@ cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; } } - - out: - *cr_out = cr; + if (names != NULL && *names != '\0' && cr->cr_ngroups == NGRPS) + syslog(LOG_ERR, "too many groups"); } #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)