From owner-freebsd-current@FreeBSD.ORG Fri Jun 5 22:36:26 2009 Return-Path: Delivered-To: current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2B4F11065696; Fri, 5 Jun 2009 22:36:26 +0000 (UTC) (envelope-from brooks@lor.one-eyed-alien.net) Received: from lor.one-eyed-alien.net (cl-162.ewr-01.us.sixxs.net [IPv6:2001:4830:1200:a1::2]) by mx1.freebsd.org (Postfix) with ESMTP id D99A78FC0C; Fri, 5 Jun 2009 22:36:24 +0000 (UTC) (envelope-from brooks@lor.one-eyed-alien.net) Received: from lor.one-eyed-alien.net (localhost [127.0.0.1]) by lor.one-eyed-alien.net (8.14.3/8.14.3) with ESMTP id n55Maatm042314; Fri, 5 Jun 2009 17:36:36 -0500 (CDT) (envelope-from brooks@lor.one-eyed-alien.net) Received: (from brooks@localhost) by lor.one-eyed-alien.net (8.14.3/8.14.3/Submit) id n55MaaFr042313; Fri, 5 Jun 2009 17:36:36 -0500 (CDT) (envelope-from brooks) Date: Fri, 5 Jun 2009 17:36:36 -0500 From: Brooks Davis To: arch@freebsd.org, current@freebsd.org Message-ID: <20090605223636.GA24364@lor.one-eyed-alien.net> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="i9LlY+UWpKt15+FH" Content-Disposition: inline User-Agent: Mutt/1.5.17 (2007-11-01) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-3.0 (lor.one-eyed-alien.net [127.0.0.1]); Fri, 05 Jun 2009 17:36:36 -0500 (CDT) Cc: Subject: RFT: Allow large values of NGROUPS_MAX X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Jun 2009 22:36:27 -0000 --i9LlY+UWpKt15+FH Content-Type: multipart/mixed; boundary="sdtB3X0nJg68CQEu" Content-Disposition: inline --sdtB3X0nJg68CQEu Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable I've been working on fixing the limit of 15 groups per user. This has primarily consisted of merging a patch from Isilon Systems which breaks the group array out of struct ucred and stores in in malloc'd storage. I've attached a patch which includes that change and increases the value of NGROUPS_MAX to 32767. It also changes references to cr_groups[0] to use the cr_gid macro and introduces a new crsetgroups() function for use by random bits of code that fill in credentials (usually partial ones) Additionally, a number of arrays that used to be of length NGROUPS have been changed to use XU_NGROUPS (from xucred) or their own definition which is 16 to avoid excessive bloat. Most of these should probably be change to use dynamic allocation. In general, when something could not take more groups, I have chosen to truncate the list rather than fail. This may raise issues with negative permissions, but complete failure is likely to cause problems for more people. If it's a major issue this can be made tunable. As I mentioned above, many thing should be redone to support dynamic allocation, but all the RPC related things can not. I'd like people to test and review this patch with the aim of getting it and some of the other work I've been doing in subversion in to 8.0. You can find all of it at http://svn.freebsd.org/base/projects/ngroups. Before any merge a couple decisions need to be made: - How large should NGROUPS_MAX be? Linux uses 65536 and we could extend things to support that, but it's probably unnecessary. =20 - Should we make any attempt to support old binaries when there are more than 16 groups? The POSIX getgroups/setgroups APIs did not anticipate this change and thus either will fail outright. We can't fix setgroups, but we might want to make an optional accommodation for getgroups to allow for truncated returns to old code. -- Brooks --sdtB3X0nJg68CQEu Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="ngroups-nosysconf.diff" Content-Transfer-Encoding: quoted-printable diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =20 #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 * ); =20 -#ifndef NGROUPS -#define NGROUPS 16 -#endif - /* * Convert network-name into unix credential */ @@ -104,7 +100,7 @@ return (0); } *gidp =3D (gid_t) atol(p); - for (gidlen =3D 0; gidlen < NGROUPS; gidlen++) { + for (gidlen =3D 0; gidlen < NGRPS; gidlen++) { p =3D strsep(&res, "\n,"); if (p =3D=3D NULL) break; @@ -157,7 +153,7 @@ static int _getgroups(uname, groups) char *uname; - gid_t groups[NGROUPS]; + gid_t groups[NGRPS]; { gid_t ngroups =3D 0; struct group *grp; @@ -169,7 +165,7 @@ while ((grp =3D getgrent())) { for (i =3D 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups =3D=3D NGROUPS) { + if (ngroups =3D=3D NGRPS) { #ifdef DEBUG fprintf(stderr, "initgroups: %s is in too many groups\n", uname); diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/contrib/pf/net/pf.c ngroups/sys/cont= rib/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 !=3D NULL) { INP_LOCK_ASSERT(inp_arg); pd->lookup.uid =3D inp_arg->inp_cred->cr_uid; - pd->lookup.gid =3D inp_arg->inp_cred->cr_groups[0]; + pd->lookup.gid =3D inp_arg->inp_cred->cr_gid; return (1); } #endif @@ -3043,7 +3043,7 @@ } #ifdef __FreeBSD__ pd->lookup.uid =3D inp->inp_cred->cr_uid; - pd->lookup.gid =3D inp->inp_cred->cr_groups[0]; + pd->lookup.gid =3D inp->inp_cred->cr_gid; INP_INFO_RUNLOCK(pi); #else pd->lookup.uid =3D inp->inp_socket->so_euid; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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; =20 cr->cr_uid =3D nfscr->nfsc_uid; - ngroups =3D (nfscr->nfsc_ngroups < NGROUPS) ? - nfscr->nfsc_ngroups : NGROUPS; - for (i =3D 0; i < ngroups; i++) - cr->cr_groups[i] =3D nfscr->nfsc_groups[i]; - cr->cr_ngroups =3D ngroups; + crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); } =20 /* @@ -295,15 +290,13 @@ =20 /* * 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) { =20 cred->cr_uid =3D 0; - cred->cr_groups[0] =3D 0; + cred->cr_gid =3D 0; cred->cr_ngroups =3D 1; } =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/fs/nfsclient/nfs_clport.c ngroups/sy= s/fs/nfsclient/nfs_clport.c --- /usr/src/sys/fs/nfsclient/nfs_clport.c 2009-05-29 12:48:03.000000000 -0= 500 +++ ngroups/sys/fs/nfsclient/nfs_clport.c 2009-06-05 15:33:54.000000000 -05= 00 @@ -976,14 +976,12 @@ void newnfs_copyincred(struct ucred *cr, struct nfscred *nfscr) { - int ngroups, i; + int i; =20 nfscr->nfsc_uid =3D cr->cr_uid; - ngroups =3D (cr->cr_ngroups > NGROUPS) ? NGROUPS : - cr->cr_ngroups; - for (i =3D 0; i < ngroups; i++) + nfscr->nfsc_ngroups =3D MIN(cr->cr_ngroups, XU_NGROUPS); + for (i =3D 0; i < nfscr->nfsc_ngroups; i++) nfscr->nfsc_groups[i] =3D cr->cr_groups[i]; - nfscr->nfsc_ngroups =3D ngroups; } =20 =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D 0; =20 /* @@ -2403,9 +2402,8 @@ (nd->nd_flag & ND_AUTHNONE))) { nd->nd_cred->cr_uid =3D credanon->cr_uid; nd->nd_cred->cr_gid =3D credanon->cr_gid; - for (i =3D 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - nd->nd_cred->cr_groups[i] =3D credanon->cr_groups[i]; - nd->nd_cred->cr_ngroups =3D i; + crsetgroups(nd->nd_cred, credanon->cr_ngroups, + credanon->cr_groups); } return (0); } diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D 0; cred->cr_uid =3D clp->lc_uid; cred->cr_gid =3D clp->lc_gid; - cred->cr_groups[0] =3D clp->lc_gid; callback =3D clp->lc_callback; NFSUNLOCKSTATE(); cred->cr_ngroups =3D 1; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 */ }; =20 #ifdef _KERNEL diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/fs/portalfs/portal_vnops.c ngroups/s= ys/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 -0= 500 @@ -311,8 +311,9 @@ =20 pcred.pcr_flag =3D ap->a_mode; pcred.pcr_uid =3D ap->a_cred->cr_uid; - pcred.pcr_ngroups =3D ap->a_cred->cr_ngroups; - bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); + pcred.pcr_ngroups =3D 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 =3D (caddr_t) &pcred; aiov[0].iov_len =3D sizeof(pcred); aiov[1].iov_base =3D pt->pt_arg; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 -05= 00 +++ 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; =20 mask =3D 0; @@ -659,17 +658,14 @@ =20 /* check group */ count =3D 0; - gp =3D cred->cr_groups; - for (; count < cred->cr_ngroups; count++, gp++) { - if (gid =3D=3D *gp) { - if (accmode & VEXEC) - mask |=3D S_IXGRP; - if (accmode & VREAD) - mask |=3D S_IRGRP; - if (accmode & VWRITE) - mask |=3D S_IWGRP; - return ((vmode & mask) =3D=3D mask ? 0 : EACCES); - } + if (groupmember(gid, cred)) { + if (accmode & VEXEC) + mask |=3D S_IXGRP; + if (accmode & VREAD) + mask |=3D S_IRGRP; + if (accmode & VWRITE) + mask |=3D S_IWGRP; + return ((vmode & mask) =3D=3D mask ? 0 : EACCES); } =20 /* check other */ diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h ngro= ups/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h --- /usr/src/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h 2009-02-28 13:28:12.000000= 000 -0600 +++ ngroups/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h 2009-06-05 15:33:54.0000000= 00 -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 =20 #define PAGE_CACHE_SIZE PAGE_SIZE =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/gnu/fs/xfs/xfs_inode.c ngroups/sys/g= nu/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 =3D nlink; ASSERT(ip->i_d.di_nlink =3D=3D nlink); ip->i_d.di_uid =3D curthread->td_ucred->cr_uid; - ip->i_d.di_gid =3D curthread->td_ucred->cr_groups[0]; + ip->i_d.di_gid =3D curthread->td_ucred->cr_gid; ip->i_d.di_projid =3D prid; memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/gnu/fs/xfs/xfs_vnodeops.c ngroups/sy= s/gnu/fs/xfs/xfs_vnodeops.c --- /usr/src/sys/gnu/fs/xfs/xfs_vnodeops.c 2009-01-21 12:45:49.000000000 -0= 600 +++ ngroups/sys/gnu/fs/xfs/xfs_vnodeops.c 2009-06-05 15:33:54.000000000 -05= 00 @@ -3379,7 +3379,7 @@ */ error =3D 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=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/kern/kern_prot.c ngroups/sys/kern/ke= rn_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 @@ =20 SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"= ); =20 +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 @@ =20 td->td_retval[0] =3D td->td_ucred->cr_rgid; #if defined(COMPAT_43) - td->td_retval[1] =3D td->td_ucred->cr_groups[0]; + td->td_retval[1] =3D td->td_ucred->cr_gid; #endif return (0); } =20 -/* - * 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) { =20 - td->td_retval[0] =3D td->td_ucred->cr_groups[0]; + td->td_retval[0] =3D td->td_ucred->cr_gid; return (0); } =20 @@ -679,7 +677,7 @@ gid !=3D 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 !=3D oldcred->cr_groups[0] && /* allow setgid(getegid()) */ + gid !=3D oldcred->cr_gid && /* allow setgid(getegid()) */ #endif (error =3D priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) !=3D 0) goto fail; @@ -691,7 +689,7 @@ */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ - gid =3D=3D oldcred->cr_groups[0] || + gid =3D=3D oldcred->cr_gid || #endif /* We are using privs. */ priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) =3D=3D 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] !=3D gid) { + if (oldcred->cr_gid !=3D gid) { change_egid(newcred, gid); setsugid(p); } @@ -766,7 +764,7 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) !=3D 0) goto fail; =20 - if (oldcred->cr_groups[0] !=3D egid) { + if (oldcred->cr_gid !=3D egid) { change_egid(newcred, egid); setsugid(p); } @@ -811,7 +809,6 @@ { struct proc *p =3D td->td_proc; struct ucred *newcred, *oldcred; - int newgroups; int error; =20 if (ngrp > NGROUPS) @@ -820,16 +817,7 @@ newcred =3D crget(); crextend(newcred, ngrp); PROC_LOCK(p); - oldcred =3D p->p_ucred; - newgroups =3D MAX(oldcred->cr_agroups, ngrp); - while (newcred->cr_agroups < newgroups) { - PROC_UNLOCK(p); - crextend(newcred, newgroups); - PROC_LOCK(p); - oldcred =3D p->p_ucred; - newgroups =3D MAX(oldcred->cr_agroups, ngrp); - } - + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setgroups(oldcred, ngrp, groups); @@ -841,7 +829,6 @@ if (error) goto fail; =20 - crcopy(newcred, oldcred); if (ngrp < 1) { /* * setgroups(0, NULL) is a legitimate way of clearing the @@ -851,8 +838,7 @@ */ newcred->cr_ngroups =3D 1; } else { - bcopy(groups, newcred->cr_groups, ngrp * sizeof(gid_t)); - newcred->cr_ngroups =3D ngrp; + crsetgroups_locked(newcred, ngrp, groups); } setsugid(p); p->p_ucred =3D newcred; @@ -964,12 +950,12 @@ =20 if (((rgid !=3D (gid_t)-1 && rgid !=3D oldcred->cr_rgid && rgid !=3D oldcred->cr_svgid) || - (egid !=3D (gid_t)-1 && egid !=3D oldcred->cr_groups[0] && + (egid !=3D (gid_t)-1 && egid !=3D oldcred->cr_gid && egid !=3D oldcred->cr_rgid && egid !=3D oldcred->cr_svgid)) && (error =3D priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) !=3D 0) goto fail; =20 - if (egid !=3D (gid_t)-1 && oldcred->cr_groups[0] !=3D egid) { + if (egid !=3D (gid_t)-1 && oldcred->cr_gid !=3D egid) { change_egid(newcred, egid); setsugid(p); } @@ -977,9 +963,9 @@ change_rgid(newcred, rgid); setsugid(p); } - if ((rgid !=3D (gid_t)-1 || newcred->cr_groups[0] !=3D newcred->cr_rgid) = && - newcred->cr_svgid !=3D newcred->cr_groups[0]) { - change_svgid(newcred, newcred->cr_groups[0]); + if ((rgid !=3D (gid_t)-1 || newcred->cr_gid !=3D newcred->cr_rgid) && + newcred->cr_svgid !=3D newcred->cr_gid) { + change_svgid(newcred, newcred->cr_gid); setsugid(p); } p->p_ucred =3D newcred; @@ -1110,17 +1096,17 @@ =20 if (((rgid !=3D (gid_t)-1 && rgid !=3D oldcred->cr_rgid && rgid !=3D oldcred->cr_svgid && - rgid !=3D oldcred->cr_groups[0]) || + rgid !=3D oldcred->cr_gid) || (egid !=3D (gid_t)-1 && egid !=3D oldcred->cr_rgid && egid !=3D oldcred->cr_svgid && - egid !=3D oldcred->cr_groups[0]) || + egid !=3D oldcred->cr_gid) || (sgid !=3D (gid_t)-1 && sgid !=3D oldcred->cr_rgid && sgid !=3D oldcred->cr_svgid && - sgid !=3D oldcred->cr_groups[0])) && + sgid !=3D oldcred->cr_gid)) && (error =3D priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) !=3D 0) goto fail; =20 - if (egid !=3D (gid_t)-1 && oldcred->cr_groups[0] !=3D egid) { + if (egid !=3D (gid_t)-1 && oldcred->cr_gid !=3D egid) { change_egid(newcred, egid); setsugid(p); } @@ -1189,8 +1175,8 @@ error1 =3D copyout(&cred->cr_rgid, uap->rgid, sizeof(cred->cr_rgid)); if (uap->egid) - error2 =3D copyout(&cred->cr_groups[0], - uap->egid, sizeof(cred->cr_groups[0])); + error2 =3D copyout(&cred->cr_gid, + uap->egid, sizeof(cred->cr_gid)); if (uap->sgid) error3 =3D copyout(&cred->cr_svgid, uap->sgid, sizeof(cred->cr_svgid)); @@ -1911,7 +1897,7 @@ ngroups =3D min(cr->cr_ngroups, XU_NGROUPS); xcr->cr_ngroups =3D ngroups; bcopy(cr->cr_groups, xcr->cr_groups, - ngroups * sizeof(cr->cr_groups[0])); + ngroups * sizeof(*cr->cr_groups)); } =20 /* @@ -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 =3D cr->cr_agroups * 2; @@ -1987,6 +1975,36 @@ } =20 /* + * 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=20 + */ +static inline void +crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) +{ +=09 + KASSERT(cr->cr_agroups >=3D ngrp, ("cr_ngroups is too small")); + + bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); + cr->cr_ngroups =3D 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 =3D 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) { =20 - newcred->cr_groups[0] =3D egid; + newcred->cr_gid =3D egid; } =20 /*- Only in /usr/src/sys/kern: kern_prot.c.orig diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/kern/vfs_export.c ngroups/sys/kern/v= fs_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 =3D argp->ex_flags; np->netc_anon =3D crget(); np->netc_anon->cr_uid =3D argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups =3D 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 =3D argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); @@ -205,9 +204,8 @@ np->netc_exflags =3D argp->ex_flags; np->netc_anon =3D crget(); np->netc_anon->cr_uid =3D argp->ex_anon.cr_uid; - np->netc_anon->cr_ngroups =3D 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 =3D argp->ex_numsecflavors; bcopy(argp->ex_secflavors, np->netc_secflavors, sizeof(np->netc_secflavors)); diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D td->td_ucred; tmpcred =3D crdup(cred); tmpcred->cr_uid =3D cred->cr_ruid; - tmpcred->cr_groups[0] =3D cred->cr_rgid; + tmpcred->cr_gid =3D cred->cr_rgid; td->td_ucred =3D tmpcred; } else cred =3D tmpcred =3D td->td_ucred; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/netinet/ipfw/ip_fw2.c ngroups/sys/ne= tinet/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 =3D inp->inp_cred; ugp->fw_prid =3D jailed(cr) ? cr->cr_prison->pr_id : -1; ugp->fw_uid =3D cr->cr_uid; - ugp->fw_ngroups =3D cr->cr_ngroups; - bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups)); + ugp->fw_ngroups =3D MIN(cr->cr_ngroups, FW_NGROUPS); + bcopy(cr->cr_groups, ugp->fw_groups, sizeof(gid_t) * ugp->fw_ngroups); } =20 static int diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D 0xFFFF; ncp->li =3D *cap; ncp->nc_group =3D (cap->group !=3D NCP_DEFAULT_GROUP) ? - cap->group : cred->cr_groups[0]; + cap->group : cred->cr_gid; =20 if (cap->retry_count =3D=3D 0) ncp->li.retry_count =3D NCP_RETRY_COUNT; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D=3D SMBM_ANY_OWNER) uid =3D realuid; if (gid =3D=3D SMBM_ANY_GROUP) - gid =3D cred->cr_groups[0]; + gid =3D cred->cr_gid; vcp->vc_uid =3D uid; vcp->vc_grp =3D gid; =20 @@ -714,7 +714,7 @@ if (uid =3D=3D SMBM_ANY_OWNER) uid =3D realuid; if (gid =3D=3D SMBM_ANY_GROUP) - gid =3D cred->cr_groups[0]; + gid =3D cred->cr_gid; ssp =3D smb_zmalloc(sizeof(*ssp), M_SMBCONN, M_WAITOK); smb_co_init(SSTOCP(ssp), SMBL_SHARE, "smbss ilock", "smbss"); ssp->obj.co_free =3D smb_share_free; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/nfsclient/nfs_subs.c ngroups/sys/nfs= client/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++ =3D 0; /* stamp ?? */ *tl++ =3D 0; /* NULL hostname */ *tl++ =3D txdr_unsigned(cr->cr_uid); - *tl++ =3D txdr_unsigned(cr->cr_groups[0]); + *tl++ =3D txdr_unsigned(cr->cr_gid); grpsiz =3D (auth_len >> 2) - 5; *tl++ =3D txdr_unsigned(grpsiz); for (i =3D 1; i <=3D grpsiz; i++) diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED); nd->nd_cr->cr_uid =3D nd->nd_cr->cr_ruid =3D nd->nd_cr->cr_svuid =3D fxdr_unsigned(uid_t, *tl++); - nd->nd_cr->cr_groups[0] =3D nd->nd_cr->cr_rgid =3D + nd->nd_cr->cr_gid =3D nd->nd_cr->cr_rgid =3D nd->nd_cr->cr_svgid =3D fxdr_unsigned(gid_t, *tl++); #ifdef MAC mac_cred_associate_nfsd(nd->nd_cr); @@ -374,7 +374,7 @@ nd->nd_cr->cr_groups[i] =3D fxdr_unsigned(gid_t, *tl++); else tl++; - nd->nd_cr->cr_ngroups =3D (len >=3D XU_NGROUPS) ? XU_NGROUPS : (len + 1); + nd->nd_cr->cr_ngroups =3D 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 =3D fxdr_unsigned(int, *++tl); Only in /usr/src/sys/nfsserver: nfs_srvsock.c.orig diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D nfsd->nd_cr; if (cred->cr_uid =3D=3D 0 || (exflags & MNT_EXPORTANON)) { cred->cr_uid =3D credanon->cr_uid; - for (i =3D 0; i < credanon->cr_ngroups && i < NGROUPS; i++) - cred->cr_groups[i] =3D credanon->cr_groups[i]; - cred->cr_ngroups =3D i; + crsetgroups(cred, credanon->cr_ngroups, credanon->cr_groups); } if (exflags & MNT_EXRDONLY) *rdonlyp =3D 1; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 @@ =20 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); =20 if (xdrs->x_op =3D=3D XDR_ENCODE) { diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c ngro= ups/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- /usr/src/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-01-22 10:05:57.000000= 000 -0600 +++ ngroups/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-05 15:33:54.0000000= 00 -0500 @@ -447,11 +447,7 @@ cr =3D client->cl_cred =3D crget(); cr->cr_uid =3D cr->cr_ruid =3D cr->cr_svuid =3D uc->uid; cr->cr_rgid =3D cr->cr_svgid =3D uc->gid; - cr->cr_ngroups =3D uc->gidlen; - if (cr->cr_ngroups > NGROUPS) - cr->cr_ngroups =3D NGROUPS; - for (i =3D 0; i < cr->cr_ngroups; i++) - cr->cr_groups[i] =3D uc->gidlist[i]; + crsetgroups(cr, uc->gidlen, uc->gidlist); *crp =3D crhold(cr); =20 return (TRUE); diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/rpc/svc_auth.c ngroups/sys/rpc/svc_a= uth.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 =3D NULL; - int flavor, i; + int flavor; struct xucred *xcr; =20 flavor =3D rqst->rq_cred.oa_flavor; @@ -177,10 +177,8 @@ xcr =3D (struct xucred *) rqst->rq_clntcred; cr =3D crget(); cr->cr_uid =3D cr->cr_ruid =3D cr->cr_svuid =3D xcr->cr_uid; - cr->cr_ngroups =3D xcr->cr_ngroups; - for (i =3D 0; i < xcr->cr_ngroups; i++) - cr->cr_groups[i] =3D xcr->cr_groups[i]; - cr->cr_rgid =3D cr->cr_svgid =3D cr->cr_groups[0]; + crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); + cr->cr_rgid =3D cr->cr_svgid =3D cr->cr_gid; *crp =3D cr; return (TRUE); =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D RNDUP(str_len); buf +=3D str_len / sizeof (int32_t); xcr->cr_uid =3D IXDR_GET_UINT32(buf); - xcr->cr_groups[0] =3D IXDR_GET_UINT32(buf); + xcr->cr_gid =3D IXDR_GET_UINT32(buf); gid_len =3D (size_t)IXDR_GET_UINT32(buf); if (gid_len > NGRPS) { stat =3D AUTH_BADCRED; goto done; } for (i =3D 0; i < gid_len; i++) { - if (i + 1 < NGROUPS) + if (i + 1 < XU_NGROUPS) xcr->cr_groups[i + 1] =3D IXDR_GET_INT32(buf); else buf++; } - if (gid_len + 1 > NGROUPS) - xcr->cr_ngroups =3D NGROUPS; + if (gid_len + 1 > XU_NGROUPS) + xcr->cr_ngroups =3D XU_NGROUPS; else xcr->cr_ngroups =3D gid_len + 1; =20 diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/security/audit/audit.c ngroups/sys/s= ecurity/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 =3D cred->cr_ruid; ar->k_ar.ar_subj_rgid =3D cred->cr_rgid; - ar->k_ar.ar_subj_egid =3D cred->cr_groups[0]; + ar->k_ar.ar_subj_egid =3D cred->cr_gid; ar->k_ar.ar_subj_auid =3D cred->cr_audit.ai_auid; ar->k_ar.ar_subj_asid =3D cred->cr_audit.ai_asid; ar->k_ar.ar_subj_pid =3D td->td_proc->p_pid; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/security/audit/audit_arg.c ngroups/s= ys/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 -0= 500 @@ -369,7 +369,7 @@ cred =3D p->p_ucred; ar->k_ar.ar_arg_auid =3D cred->cr_audit.ai_auid; ar->k_ar.ar_arg_euid =3D cred->cr_uid; - ar->k_ar.ar_arg_egid =3D cred->cr_groups[0]; + ar->k_ar.ar_arg_egid =3D cred->cr_gid; ar->k_ar.ar_arg_ruid =3D cred->cr_ruid; ar->k_ar.ar_arg_rgid =3D cred->cr_rgid; ar->k_ar.ar_arg_asid =3D cred->cr_audit.ai_asid; diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/sys/sys/syslimits.h ngroups/sys/sys/sysl= imits.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=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =20 /* 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 */ =20 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=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$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 =3D ip->i_uid; ucred.cr_ngroups =3D 1; - ucred.cr_groups[0] =3D dp->i_gid; + ucred.cr_gid =3D dp->i_gid; ucp =3D &ucred; } #endif @@ -2266,6 +2266,7 @@ { #ifdef QUOTA struct ucred ucred, *ucp; + gid_t ucred_group; ucp =3D cnp->cn_cred; #endif /* @@ -2292,7 +2293,8 @@ refcount_init(&ucred.cr_ref, 1); ucred.cr_uid =3D ip->i_uid; ucred.cr_ngroups =3D 1; - ucred.cr_groups[0] =3D pdir->i_gid; + ucred.cr_groups =3D &ucred_group; + ucred.cr_gid =3D pdir->i_gid; ucp =3D &ucred; #endif } else { diff -ru --exclude=3D'.glimpse*' --exclude=3D.svn --exclude=3Dcompile --ign= ore-matching=3D'$FreeBSD' /usr/src/usr.sbin/mountd/mountd.c ngroups/usr.sbi= n/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 =3D 0; int resvport_only =3D 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; =20 @@ -1185,7 +1186,7 @@ * Set defaults. */ has_host =3D FALSE; - anon =3D &def_anon; + anon =3D def_anon; exflags =3D MNT_EXPORTED; got_nondir =3D 0; opt_flags =3D 0; @@ -1403,7 +1404,7 @@ */ grp =3D 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); } =20 -static void -xcr_grow(struct xucred **cr, int *cr_ngroups, int desired_groups) -{ - struct xucred *in =3D *cr, *out; - int n; - - if (in && *cr_ngroups > desired_groups) - return; - - n =3D MAX(XU_NGROUPS, *cr_ngroups); - while (n < desired_groups) - n *=3D 2; - - out =3D malloc(XUCRED_SIZE(n)); - if (out =3D=3D NULL) - out_of_mem(); - - if (in) { - memcpy(out, in, XUCRED_SIZE(*cr_ngroups)); - if (in !=3D &def_anon) - free(in); - } - - *cr =3D out; - *cr_ngroups =3D 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 =3D NULL; - int cr_ngroups =3D 0; - int error; =20 - xcr_grow(&cr, &cr_ngroups, 0); cr->cr_version =3D XUCRED_VERSION; /* * Set up the unprivileged user. @@ -2690,20 +2662,20 @@ if (names =3D=3D NULL) { if (pw =3D=3D NULL) { syslog(LOG_ERR, "unknown user: %s", name); - goto out; + return; } cr->cr_uid =3D pw->pw_uid; - for (;;) { - ngroups =3D cr_ngroups; - error =3D getgrouplist(pw->pw_name, pw->pw_gid, - cr->cr_groups, &ngroups); - if (!error) - break; - xcr_grow(&cr, &cr_ngroups, ngroups); - } - cr->cr_ngroups =3D ngroups; - - goto out; + ngroups =3D NGRPS + 1; + if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) + syslog(LOG_ERR, "too many groups"); + /* + * Compress out duplicate. + */ + cr->cr_ngroups =3D ngroups - 1; + cr->cr_groups[0] =3D groups[0]; + for (cnt =3D 2; cnt < ngroups; cnt++) + cr->cr_groups[cnt - 1] =3D groups[cnt]; + return; } /* * Explicit credential specified as a colon separated list: @@ -2715,11 +2687,10 @@ cr->cr_uid =3D atoi(name); else { syslog(LOG_ERR, "unknown user: %s", name); - goto out; + return; } cr->cr_ngroups =3D 0; - while (names !=3D NULL && *names !=3D '\0') { - xcr_grow(&cr, &cr_ngroups, cr->cr_ngroups + 1); + while (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups < NGRPS) { name =3D strsep(&names, ":"); if (isdigit(*name) || *name =3D=3D '-') { cr->cr_groups[cr->cr_ngroups++] =3D atoi(name); @@ -2731,9 +2702,8 @@ cr->cr_groups[cr->cr_ngroups++] =3D gr->gr_gid; } } - - out: - *cr_out =3D cr; + if (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups =3D=3D NGRPS) + syslog(LOG_ERR, "too many groups"); } =20 #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) --sdtB3X0nJg68CQEu-- --i9LlY+UWpKt15+FH Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iD8DBQFKKZ3zXY6L6fI4GtQRAmZIAJ9vmvoOMbiS30WRBzsHqpjAx+fdMQCg21bB l7/uY3WXqja2MHK21xWk4a4= =acSA -----END PGP SIGNATURE----- --i9LlY+UWpKt15+FH--