From owner-freebsd-current@FreeBSD.ORG Thu Jun 18 00:05:21 2009 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 38425106564A; Thu, 18 Jun 2009 00:05:21 +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 BDD9B8FC1C; Thu, 18 Jun 2009 00:05:19 +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 n5I05VUI046057; Wed, 17 Jun 2009 19:05:31 -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 n5I05VQW046056; Wed, 17 Jun 2009 19:05:31 -0500 (CDT) (envelope-from brooks) Date: Wed, 17 Jun 2009 19:05:31 -0500 From: Brooks Davis To: freebsd-hackers@freebsd.org, freebsd-current@freebsd.org Message-ID: <20090618000531.GA46033@lor.one-eyed-alien.net> References: <20090618000407.GA43514@lor.one-eyed-alien.net> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="O5XBE6gyVG5Rl6Rj" Content-Disposition: inline In-Reply-To: <20090618000407.GA43514@lor.one-eyed-alien.net> 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]); Wed, 17 Jun 2009 19:05:31 -0500 (CDT) Cc: Subject: Re: CFT: final patches for NGROUPS>>16 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: Thu, 18 Jun 2009 00:05:21 -0000 --O5XBE6gyVG5Rl6Rj Content-Type: multipart/mixed; boundary="YZ5djTAD1cGYuMQK" Content-Disposition: inline --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable As usual, I forgot the attachments. Here they are. -- Brooks On Wed, Jun 17, 2009 at 07:04:07PM -0500, Brooks Davis wrote: > Please find attached three patches which result in raising NGROUPS to > 1024, making programs in the base system immune to changing values of > NGROUPS, and pave the way for NGROUPS to be boot time configurable. >=20 > The first two patches (ngroups-catman.diff and ngroups-posix.diff) > are userland cleanups. The third (ngroups-main.diff) is the core of > the change and primairly in the kernel. It is strongly based on work > contributed by Isilon Systems. The proposed commit messages appear to > the bottom of this message. >=20 > I've been running the basic code on my FreeBSD laptop for a while and > I've tested basic NFS mounts, but more areas need testing before this > hits a release. Key things to hit include: > - NFS mount and export > - IPFW uid, gid, and jail rules > - portalfs (ideally portalfs should be extended to not truncate groups) >=20 > In practice, expect appliations to not care about this change unless > they are run with more than 16 groups. If that happens, calls to > getgroups() will fail if they use statically sized buffers recompilation > should fix them. >=20 > Please test, review, etc. I'd like to get this in before code freeze if > at all possible. >=20 > -- Brooks >=20 > ngroups-catman.diff: >=20 > When checking if we can write to a file, use access() instead of a > manual permission check based on stat output. Also, get rid of the > executability check since it is not used. >=20 > MFC after: 2 weeks >=20 > ngroups-posix.diff >=20 > In preparation for raising NGROUPS and NGROUPS_MAX, change base > system callers of getgroups(), getgrouplist(), and setgroups() to > allocate buffers dynamically. Specifically, allocate a buffer of size > sysconf(_SC_NGROUPS_MAX)+1 (+2 in a few cases to allow for overflow). >=20 > This (or similar gymnastics) is required for the code to actually follow > the POSIX.1-2008 specification where {NGROUPS_MAX} may differ at runtime > and where getgroups may return {NGROUPS_MAX}+1 results on systems like > FreeBSD which include the primary group. >=20 > In id(1), don't pointlessly add the primary group to the list of all > groups, it is always the first result from getgroups(). In principle > the old code was more portable, but this was only done in one of the two > places where getgroups() was called to the overall effect was pointless. >=20 > Document the actual POSIX requirements in the getgroups(2) and > setgroups(2) manpages. We do not yet support a dynamic NGROUPS, but we > may in the future. >=20 > MFC after: 2 weeks >=20 > ngroups-main.diff: >=20 > Rework the credential code to support larger values of NGROUPS and > NGROUPS_MAX, eliminate ABI dependencies on them, and raise the to 1024 > and 1023 respectively. (Previously they were equal, but under a close > reading of POSIX, NGROUPS_MAX was defined to be too large by 1 since it > is the number of supplemental groups, not total number of groups.) >=20 > The bulk of the change consists of converting the struct ucred member > cr_groups from a static array to a pointer. Do the equivalent in > kinfo_proc. >=20 > Introduce new interfaces crcopysafe() and crsetgroups() for duplicating > a process credential before modifying it and for setting group lists > respectively. Both interfaces take care for the details of allocating > groups array. crsetgroups() takes care of truncating the group list > to the current maximum (NGROUPS) if necessary. In the future, > crsetgroups() may be responsible for insuring invariants such as sorting > the supplemental groups to allow groupmember() to be implemented as a > binary search. >=20 > Because we can not change struct xucred without breaking application > ABIs, we leave it alone and introduce a new XU_NGROUPS value which is > always 16 and is to be used or NGRPS as appropriate for things such as > NFS which need to use no more than 16 groups. When feasible, truncate > the group list rather than generating an error. >=20 > Minor changes: > - Reduce the number of hand rolled versions of groupmember(). > - Do not assign to both cr_gid and cr_groups[0]. > - Modify ipfw to cache ucreds instead of part of their contents since > they are immutable once referenced by more than one entity. >=20 > Submitted by: Isilon Systems > X-MFC after: never --YZ5djTAD1cGYuMQK Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="ngroups-catman.diff" Content-Transfer-Encoding: quoted-printable diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.bin/catman/catman.c ./usr.bin/c= atman/catman.c --- /usr/fsvn/head/usr.bin/catman/catman.c 2009-01-22 10:04:12.000000000 -0= 600 +++ ./usr.bin/catman/catman.c 2009-05-08 15:47:47.000000000 -0500 @@ -57,7 +57,6 @@ #define TEST_FILE 0x04 #define TEST_READABLE 0x08 #define TEST_WRITABLE 0x10 -#define TEST_EXECUTABLE 0x20 =20 static int verbose; /* -v flag: be verbose with warnings */ static int pretend; /* -n, -p flags: print out what would be done @@ -92,9 +91,6 @@ #define GZCAT_CMD "z" enum Ziptype {NONE, BZIP, GZIP}; =20 -static uid_t uid; -static gid_t gids[NGROUPS_MAX]; -static int ngids; static int starting_dir; static char tmp_file[MAXPATHLEN]; struct stat test_st; @@ -320,23 +316,10 @@ result |=3D TEST_DIR; else if (S_ISREG(test_st.st_mode)) result |=3D TEST_FILE; - if (test_st.st_uid =3D=3D uid) { - test_st.st_mode >>=3D 6; - } else { - int i; - for (i =3D 0; i < ngids; i++) { - if (test_st.st_gid =3D=3D gids[i]) { - test_st.st_mode >>=3D 3; - break; - } - } - } - if (test_st.st_mode & S_IROTH) + if (access(name, R_OK)) result |=3D TEST_READABLE; - if (test_st.st_mode & S_IWOTH) + if (access(name, W_OK)) result |=3D TEST_WRITABLE; - if (test_st.st_mode & S_IXOTH) - result |=3D TEST_EXECUTABLE; return result; } =20 @@ -759,14 +742,6 @@ { int opt; =20 - if ((uid =3D getuid()) =3D=3D 0) { - fprintf(stderr, "don't run %s as root, use:\n echo", argv[0]); - for (optind =3D 0; optind < argc; optind++) { - fprintf(stderr, " %s", argv[optind]); - } - fprintf(stderr, " | nice -5 su -m man\n"); - exit(1); - } while ((opt =3D getopt(argc, argv, "vnfLrh")) !=3D -1) { switch (opt) { case 'f': @@ -789,7 +764,6 @@ /* NOTREACHED */ } } - ngids =3D getgroups(NGROUPS_MAX, gids); if ((starting_dir =3D open(".", 0)) < 0) { err(1, "."); } --YZ5djTAD1cGYuMQK Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="ngroups-posix.diff" Content-Transfer-Encoding: quoted-printable diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/gen/initgroups.3 ./lib/lib= c/gen/initgroups.3 --- /usr/fsvn/head/lib/libc/gen/initgroups.3 2009-01-22 10:05:45.000000000 = -0600 +++ ./lib/libc/gen/initgroups.3 2009-06-09 09:17:36.000000000 -0500 @@ -65,6 +65,13 @@ .Va errno for any of the errors specified for the library function .Xr setgroups 2 . +It may also return: +.Bl -tag -width Er +.It Bq Er ENOMEM +The +.Fn initgroups +function was unable to allocate temporary storage. +.El .Sh SEE ALSO .Xr setgroups 2 , .Xr getgrouplist 3 diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/gen/initgroups.c ./lib/lib= c/gen/initgroups.c --- /usr/fsvn/head/lib/libc/gen/initgroups.c 2009-01-22 10:05:45.000000000 = -0600 +++ ./lib/libc/gen/initgroups.c 2009-06-17 14:00:59.000000000 -0500 @@ -35,10 +35,12 @@ =20 #include =20 -#include #include "namespace.h" #include #include "un-namespace.h" +#include +#include +#include #include =20 int @@ -46,14 +48,21 @@ const char *uname; gid_t agroup; { - int ngroups; + int ngroups, ret; + long ngroups_max; + gid_t *groups; + /* - * Provide space for one group more than NGROUPS to allow + * Provide space for one group more than possible to allow * setgroups to fail and set errno. */ - gid_t groups[NGROUPS + 1]; + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 2; + if ((groups =3D malloc(sizeof(*groups) * ngroups_max)) =3D=3D NULL) + return (ENOMEM); =20 - ngroups =3D NGROUPS + 1; + ngroups =3D (int)ngroups_max; getgrouplist(uname, agroup, groups, &ngroups); - return (setgroups(ngroups, groups)); + ret =3D setgroups(ngroups, groups); + free(groups); + return (ret); } diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/rpc/auth_unix.c ./lib/libc= /rpc/auth_unix.c --- /usr/fsvn/head/lib/libc/rpc/auth_unix.c 2009-01-22 10:05:43.000000000 -= 0600 +++ ./lib/libc/rpc/auth_unix.c 2009-06-17 14:00:59.000000000 -0500 @@ -185,23 +185,29 @@ AUTH * authunix_create_default() { - int len; + int ngids; + long ngids_max; char machname[MAXHOSTNAMELEN + 1]; uid_t uid; gid_t gid; - gid_t gids[NGROUPS_MAX]; + gid_t *gids; + + ngids_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + gids =3D malloc(sizeof(gid_t) * ngids_max); + if (gids =3D=3D NULL) + return (NULL); =20 if (gethostname(machname, sizeof machname) =3D=3D -1) abort(); machname[sizeof(machname) - 1] =3D 0; uid =3D geteuid(); gid =3D getegid(); - if ((len =3D getgroups(NGROUPS_MAX, gids)) < 0) + if ((ngids =3D getgroups(ngids_max, gids)) < 0) abort(); - if (len > NGRPS) - len =3D NGRPS; + if (ngids > NGRPS) + ngids =3D NGRPS; /* XXX: interface problem; those should all have been unsigned */ - return (authunix_create(machname, (int)uid, (int)gid, len, + return (authunix_create(machname, (int)uid, (int)gid, ngids, (int *)gids)); } =20 diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/sys/getgroups.2 ./lib/libc= /sys/getgroups.2 --- /usr/fsvn/head/lib/libc/sys/getgroups.2 2009-01-22 10:05:48.000000000 -= 0600 +++ ./lib/libc/sys/getgroups.2 2009-06-16 13:56:17.000000000 -0500 @@ -58,10 +58,7 @@ system call returns the actual number of groups returned in .Fa gidset . -No more than -.Dv NGROUPS_MAX -will ever -be returned. +At least one and as many as {NGROUPS_MAX}+1 values may be returned. If .Fa gidsetlen is zero, @@ -92,6 +89,11 @@ .Sh SEE ALSO .Xr setgroups 2 , .Xr initgroups 3 +.Sh STANDARDS +The +.Fn getgroups +system call conforms to +.St -p1003.1-2008 . .Sh HISTORY The .Fn getgroups diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/sys/setgroups.2 ./lib/libc= /sys/setgroups.2 --- /usr/fsvn/head/lib/libc/sys/setgroups.2 2009-01-22 10:05:48.000000000 -= 0600 +++ ./lib/libc/sys/setgroups.2 2009-06-16 13:56:17.000000000 -0500 @@ -53,9 +53,7 @@ argument indicates the number of entries in the array and must be no more than -.Dv NGROUPS , -as defined in -.In sys/param.h . +.Dv {NGROUPS_MAX}+1 . .Pp Only the super-user may set a new group list. .Sh RETURN VALUES @@ -71,7 +69,7 @@ The number specified in the .Fa ngroups argument is larger than the -.Dv NGROUPS +.Dv {NGROUPS_MAX}+1 limit. .It Bq Er EFAULT The address specified for diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.bin/id/id.c ./usr.bin/id/id.c --- /usr/fsvn/head/usr.bin/id/id.c 2009-01-22 10:04:13.000000000 -0600 +++ ./usr.bin/id/id.c 2009-06-17 14:00:59.000000000 -0500 @@ -258,7 +258,8 @@ gid_t gid, egid, lastgid; uid_t uid, euid; int cnt, ngroups; - gid_t groups[NGROUPS + 1]; + long ngroups_max; + gid_t *groups; const char *fmt; =20 if (pw !=3D NULL) { @@ -270,12 +271,16 @@ gid =3D getgid(); } =20 + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); + if (use_ggl && pw !=3D NULL) { - ngroups =3D NGROUPS + 1; + ngroups =3D ngroups_max; getgrouplist(pw->pw_name, gid, groups, &ngroups); } else { - ngroups =3D getgroups(NGROUPS + 1, groups); + ngroups =3D getgroups(ngroups_max, groups); } =20 if (pw !=3D NULL) @@ -306,6 +311,7 @@ lastgid =3D gid; } printf("\n"); + free(groups); } =20 #ifdef USE_BSM_AUDIT @@ -361,15 +367,19 @@ { struct group *gr; int cnt, id, lastid, ngroups; - gid_t groups[NGROUPS + 1]; + long ngroups_max; + gid_t *groups; const char *fmt; =20 + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups =3D malloc(sizeof(gid_t) * (ngroups_max))) =3D=3D NULL) + err(1, "malloc"); + if (pw) { - ngroups =3D NGROUPS + 1; + ngroups =3D ngroups_max; (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); } else { - groups[0] =3D getgid(); - ngroups =3D getgroups(NGROUPS, groups + 1) + 1; + ngroups =3D getgroups(ngroups_max, groups); } fmt =3D nflag ? "%s" : "%u"; for (lastid =3D -1, cnt =3D 0; cnt < ngroups; ++cnt) { @@ -389,6 +399,7 @@ lastid =3D id; } (void)printf("\n"); + free(groups); } =20 void diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.bin/newgrp/newgrp.c ./usr.bin/n= ewgrp/newgrp.c --- /usr/fsvn/head/usr.bin/newgrp/newgrp.c 2009-01-22 10:04:11.000000000 -0= 600 +++ ./usr.bin/newgrp/newgrp.c 2009-06-17 14:00:59.000000000 -0500 @@ -146,8 +146,8 @@ static void addgroup(const char *grpname) { - gid_t grps[NGROUPS_MAX]; - long lgid; + gid_t *grps; + long lgid, ngrps_max; int dbmember, i, ngrps; gid_t egid; struct group *grp; @@ -185,7 +185,10 @@ } } =20 - if ((ngrps =3D getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) { + ngrps_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((grps =3D malloc(sizeof(gid_t) * ngrps_max)) =3D=3D NULL) + err(1, "malloc"); + if ((ngrps =3D getgroups(ngrps_max, (gid_t *)grps)) < 0) { warn("getgroups"); return; } @@ -217,7 +220,7 @@ =20 /* Add old effective gid to supp. list if it does not exist. */ if (egid !=3D grp->gr_gid && !inarray(egid, grps, ngrps)) { - if (ngrps =3D=3D NGROUPS_MAX) + if (ngrps =3D=3D ngrps_max) warnx("too many groups"); else { grps[ngrps++] =3D egid; @@ -231,6 +234,7 @@ } } =20 + free(grps); } =20 static int diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.bin/quota/quota.c ./usr.bin/quo= ta/quota.c --- /usr/fsvn/head/usr.bin/quota/quota.c 2009-01-22 10:04:12.000000000 -0600 +++ ./usr.bin/quota/quota.c 2009-06-17 14:00:59.000000000 -0500 @@ -117,7 +117,8 @@ main(int argc, char *argv[]) { int ngroups;=20 - gid_t mygid, gidset[NGROUPS]; + long ngroups_max; + gid_t mygid, *gidset; int i, ch, gflag =3D 0, uflag =3D 0, errflag =3D 0; =20 while ((ch =3D getopt(argc, argv, "f:ghlrquv")) !=3D -1) { @@ -159,13 +160,18 @@ errflag +=3D showuid(getuid()); if (gflag) { mygid =3D getgid(); - ngroups =3D getgroups(NGROUPS, gidset); + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((gidset =3D malloc(sizeof(gid_t) * ngroups_max)) + =3D=3D NULL) + err(1, "malloc"); + ngroups =3D getgroups(ngroups_max, gidset); if (ngroups < 0) err(1, "getgroups"); errflag +=3D showgid(mygid); for (i =3D 0; i < ngroups; i++) if (gidset[i] !=3D mygid) errflag +=3D showgid(gidset[i]); + free(gidset); } return(errflag); } diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/chown/chown.c ./usr.sbin/c= hown/chown.c --- /usr/fsvn/head/usr.sbin/chown/chown.c 2009-01-22 10:05:31.000000000 -06= 00 +++ ./usr.sbin/chown/chown.c 2009-06-17 14:00:59.000000000 -0500 @@ -269,7 +269,8 @@ { static uid_t euid =3D -1; static int ngroups =3D -1; - gid_t groups[NGROUPS_MAX]; + static long ngroups_max; + gid_t *groups; =20 /* Check for chown without being root. */ if (errno !=3D EPERM || (uid !=3D (uid_t)-1 && @@ -281,7 +282,10 @@ /* Check group membership; kernel just returns EPERM. */ if (gid !=3D (gid_t)-1 && ngroups =3D=3D -1 && euid =3D=3D (uid_t)-1 && (euid =3D geteuid()) !=3D 0) { - ngroups =3D getgroups(NGROUPS_MAX, groups); + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); + ngroups =3D getgroups(ngroups_max, groups); while (--ngroups >=3D 0 && gid !=3D groups[ngroups]); if (ngroups < 0) { warnx("you are not a member of group %s", gname); diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/chroot/chroot.c ./usr.sbin= /chroot/chroot.c --- /usr/fsvn/head/usr.sbin/chroot/chroot.c 2009-01-22 10:05:34.000000000 -= 0600 +++ ./usr.sbin/chroot/chroot.c 2009-06-17 14:00:59.000000000 -0500 @@ -69,9 +69,10 @@ struct passwd *pw; char *endp, *p; const char *shell; - gid_t gid, gidlist[NGROUPS_MAX]; + gid_t gid, *gidlist; uid_t uid; int ch, gids; + long ngroups_max; =20 gid =3D 0; uid =3D 0; @@ -117,8 +118,11 @@ } } =20 + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((gidlist =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); for (gids =3D 0; - (p =3D strsep(&grouplist, ",")) !=3D NULL && gids < NGROUPS_MAX; ) { + (p =3D strsep(&grouplist, ",")) !=3D NULL && gids < ngroups_max; ) { if (*p =3D=3D '\0') continue; =20 @@ -135,7 +139,7 @@ } gids++; } - if (p !=3D NULL && gids =3D=3D NGROUPS_MAX) + if (p !=3D NULL && gids =3D=3D ngroups_max) errx(1, "too many supplementary groups provided"); =20 if (user !=3D NULL) { diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/jail/jail.c ./usr.sbin/jai= l/jail.c --- /usr/fsvn/head/usr.sbin/jail/jail.c 2009-06-12 00:52:16.000000000 -0500 +++ ./usr.sbin/jail/jail.c 2009-06-17 14:00:59.000000000 -0500 @@ -104,7 +104,7 @@ lcap =3D login_getpwclass(pwd); \ if (lcap =3D=3D NULL) \ err(1, "getpwclass: %s", username); \ - ngroups =3D NGROUPS; \ + ngroups =3D ngroups_max; \ if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) !=3D 0) \ err(1, "getgrouplist: %s", username); \ } while (0) @@ -115,10 +115,11 @@ login_cap_t *lcap =3D NULL; struct iovec rparams[2]; struct passwd *pwd =3D NULL; - gid_t groups[NGROUPS]; + gid_t *groups; size_t sysvallen; int ch, cmdarg, i, jail_set_flags, jid, ngroups, sysval; int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag; + long ngroups_max; unsigned pi; char *ep, *jailname, *securelevel, *username, *JidFile; char errmsg[ERRMSG_SIZE], enforce_statfs[4]; @@ -132,6 +133,10 @@ jailname =3D securelevel =3D username =3D JidFile =3D cleanenv =3D NULL; fp =3D NULL; =20 + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1;=09 + if ((groups =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); + while ((ch =3D getopt(argc, argv, "cdhilmn:r:s:u:U:J:")) !=3D -1) { switch (ch) { case 'd': diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/jexec/jexec.c ./usr.sbin/j= exec/jexec.c --- /usr/fsvn/head/usr.sbin/jexec/jexec.c 2009-05-29 12:48:00.000000000 -05= 00 +++ ./usr.sbin/jexec/jexec.c 2009-06-17 14:00:59.000000000 -0500 @@ -59,7 +59,7 @@ lcap =3D login_getpwclass(pwd); \ if (lcap =3D=3D NULL) \ err(1, "getpwclass: %s", username); \ - ngroups =3D NGROUPS; \ + ngroups =3D ngroups_max; \ if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) !=3D 0) \ err(1, "getgrouplist: %s", username); \ } while (0) @@ -71,12 +71,17 @@ int jid; login_cap_t *lcap =3D NULL; struct passwd *pwd =3D NULL; - gid_t groups[NGROUPS]; + gid_t *groups =3D NULL; int ch, ngroups, uflag, Uflag; + long ngroups_max; char *ep, *username; ch =3D uflag =3D Uflag =3D 0; username =3D NULL; =20 + ngroups_max =3D sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); + while ((ch =3D getopt(argc, argv, "nu:U:")) !=3D -1) { switch (ch) { case 'n': diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/lpr/lpc/lpc.c ./usr.sbin/l= pr/lpc/lpc.c --- /usr/fsvn/head/usr.sbin/lpr/lpc/lpc.c 2009-01-22 10:05:32.000000000 -06= 00 +++ ./usr.sbin/lpr/lpc/lpc.c 2009-06-17 14:00:59.000000000 -0500 @@ -356,7 +356,8 @@ { static struct group *gptr=3DNULL; static int ngroups =3D 0; - static gid_t groups[NGROUPS]; + static long ngroups_max; + static gid_t *groups; register gid_t gid; register int i; =20 @@ -365,7 +366,10 @@ warnx("warning: unknown group '%s'", grname); return(0); } - ngroups =3D getgroups(NGROUPS, groups); + ngroups_max =3D sysconf(_SC_NGROUPS_MAX); + if ((groups =3D malloc(sizeof(gid_t) * ngroups_max)) =3D=3D NULL) + err(1, "malloc"); + ngroups =3D getgroups(ngroups_max, groups); if (ngroups < 0) err(1, "getgroups"); } --YZ5djTAD1cGYuMQK Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="ngroups-main.diff" Content-Transfer-Encoding: quoted-printable diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/rpc/netname.c ./lib/libc/r= pc/netname.c --- /usr/fsvn/head/lib/libc/rpc/netname.c 2009-01-22 10:05:44.000000000 -06= 00 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libc/rpc/netnamer.c ./lib/libc/= rpc/netnamer.c --- /usr/fsvn/head/lib/libc/rpc/netnamer.c 2009-01-22 10:05:44.000000000 -0= 600 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/lib/libkvm/kvm_proc.c ./lib/libkvm/= kvm_proc.c --- /usr/fsvn/head/lib/libkvm/kvm_proc.c 2009-06-16 15:54:14.000000000 -0500 +++ ./lib/libkvm/kvm_proc.c 2009-05-28 16:40:33.000000000 -0500 @@ -146,8 +146,7 @@ kp->ki_rgid =3D ucred.cr_rgid; kp->ki_svgid =3D ucred.cr_svgid; kp->ki_ngroups =3D ucred.cr_ngroups; - bcopy(ucred.cr_groups, kp->ki_groups, - NGROUPS * sizeof(gid_t)); + kp->ki_groups =3D ucred.cr_groups; kp->ki_uid =3D ucred.cr_uid; if (ucred.cr_prison !=3D NULL) { if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) { Files /usr/fsvn/head/share/examples/kld/firmware/fwimage/firmware.img and .= /share/examples/kld/firmware/fwimage/firmware.img differ Only in /usr/fsvn/head/sys: .glimpse_exclude Only in /usr/fsvn/head/sys: .glimpse_filenames Only in /usr/fsvn/head/sys: .glimpse_filenames_index Only in /usr/fsvn/head/sys: .glimpse_filetimes Only in /usr/fsvn/head/sys: .glimpse_index Only in /usr/fsvn/head/sys: .glimpse_messages Only in /usr/fsvn/head/sys: .glimpse_partitions Only in /usr/fsvn/head/sys: .glimpse_statistics Only in /usr/fsvn/head/sys: .glimpse_turbo diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/compat/linux/linux_misc.c ./sys= /compat/linux/linux_misc.c --- /usr/fsvn/head/sys/compat/linux/linux_misc.c 2009-06-16 15:54:53.000000= 000 -0500 +++ ./sys/compat/linux/linux_misc.c 2009-06-16 13:56:19.000000000 -0500 @@ -1132,7 +1132,7 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { struct ucred *newcred, *oldcred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -1140,13 +1140,14 @@ ngrp =3D args->gidsetsize; if (ngrp < 0 || ngrp >=3D NGROUPS) return (EINVAL); + linux_gidset =3D malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error =3D copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) - return (error); + goto out; newcred =3D crget(); p =3D td->td_proc; PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 /* * cr_groups[0] holds egid. Setting the whole set from @@ -1157,10 +1158,9 @@ if ((error =3D priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) !=3D 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } =20 - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups =3D ngrp + 1; =20 @@ -1177,14 +1177,17 @@ p->p_ucred =3D newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error =3D 0; +out: + free(linux_gidset, M_TEMP); + return (error); } =20 int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { struct ucred *cred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; =20 @@ -1207,13 +1210,16 @@ return (EINVAL); =20 ngrp =3D 0; + linux_gidset =3D malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] =3D bsd_gidset[ngrp + 1]; ngrp++; } =20 - if ((error =3D copyout(linux_gidset, args->grouplist, - ngrp * sizeof(l_gid_t)))) + error =3D copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); + free(linux_gidset, M_TEMP); + if (error) return (error); =20 td->td_retval[0] =3D ngrp; diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/compat/linux/linux_uid16.c ./sy= s/compat/linux/linux_uid16.c --- /usr/fsvn/head/sys/compat/linux/linux_uid16.c 2009-06-16 15:54:53.00000= 0000 -0500 +++ ./sys/compat/linux/linux_uid16.c 2009-05-28 16:40:33.000000000 -0500 @@ -98,7 +98,7 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) { struct ucred *newcred, *oldcred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -111,13 +111,14 @@ ngrp =3D args->gidsetsize; if (ngrp < 0 || ngrp >=3D NGROUPS) return (EINVAL); + linux_gidset =3D malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error =3D copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t)); if (error) return (error); newcred =3D crget(); p =3D td->td_proc; PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 /* * cr_groups[0] holds egid. Setting the whole set from @@ -128,10 +129,9 @@ if ((error =3D priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) !=3D 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } =20 - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups =3D ngrp + 1; =20 @@ -149,14 +149,17 @@ p->p_ucred =3D newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error =3D 0; +out: + free(linux_gidset, M_TEMP); + return (error); } =20 int linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) { struct ucred *cred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; =20 @@ -184,12 +187,15 @@ return (EINVAL); =20 ngrp =3D 0; + linux_gidset =3D malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] =3D bsd_gidset[ngrp + 1]; ngrp++; } =20 error =3D copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t)); + free(linux_gidset, M_TEMP); if (error) return (error); =20 diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/nfs/nfs_commonport.c ./sys/f= s/nfs/nfs_commonport.c --- /usr/fsvn/head/sys/fs/nfs/nfs_commonport.c 2009-05-29 12:48:03.00000000= 0 -0500 +++ ./sys/fs/nfs/nfs_commonport.c 2009-06-09 08:49:37.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 /* diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/nfsclient/nfs_clport.c ./sys= /fs/nfsclient/nfs_clport.c --- /usr/fsvn/head/sys/fs/nfsclient/nfs_clport.c 2009-05-29 12:48:03.000000= 000 -0500 +++ ./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; =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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdport.c ./s= ys/fs/nfsserver/nfs_nfsdport.c --- /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdport.c 2009-06-05 15:33:50.0000= 00000 -0500 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdstate.c ./= sys/fs/nfsserver/nfs_nfsdstate.c --- /usr/fsvn/head/sys/fs/nfsserver/nfs_nfsdstate.c 2009-06-16 13:55:57.000= 000000 -0500 +++ ./sys/fs/nfsserver/nfs_nfsdstate.c 2009-06-16 13:56:18.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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/portalfs/portal.h ./sys/fs/p= ortalfs/portal.h --- /usr/fsvn/head/sys/fs/portalfs/portal.h 2009-01-22 10:06:01.000000000 -= 0600 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/portalfs/portal_vnops.c ./sy= s/fs/portalfs/portal_vnops.c --- /usr/fsvn/head/sys/fs/portalfs/portal_vnops.c 2009-01-22 10:06:01.00000= 0000 -0600 +++ ./sys/fs/portalfs/portal_vnops.c 2009-06-05 15:33:54.000000000 -0500 @@ -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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/fs/unionfs/union_vnops.c ./sys/= fs/unionfs/union_vnops.c --- /usr/fsvn/head/sys/fs/unionfs/union_vnops.c 2009-04-12 15:26:52.0000000= 00 -0500 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/i386/ibcs2/ibcs2_misc.c ./sys/i= 386/ibcs2/ibcs2_misc.c --- /usr/fsvn/head/sys/i386/ibcs2/ibcs2_misc.c 2009-06-16 15:54:53.00000000= 0 -0500 +++ ./sys/i386/ibcs2/ibcs2_misc.c 2009-06-05 16:02:31.000000000 -0500 @@ -657,24 +657,29 @@ struct thread *td; struct ibcs2_getgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t *iset; + gid_t *gp; u_int i, ngrp; int error; =20 if (uap->gidsetsize < 0) return (EINVAL); ngrp =3D MIN(uap->gidsetsize, NGROUPS_MAX); + gp =3D malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); error =3D kern_getgroups(td, &ngrp, gp); if (error) - return (error); + goto out; if (uap->gidsetsize > 0) { + iset =3D malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); for (i =3D 0; i < ngrp; i++) iset[i] =3D (ibcs2_gid_t)gp[i]; error =3D copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); + free(iset, M_TEMP); } if (error =3D=3D 0) td->td_retval[0] =3D ngrp; +out: + free(gp, M_TEMP); return (error); } =20 @@ -683,21 +688,31 @@ struct thread *td; struct ibcs2_setgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t *iset; + gid_t *gp; int error, i; =20 if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX) return (EINVAL); - if (uap->gidsetsize && uap->gidset) { + if (uap->gidsetsize && uap->gidset =3D=3D NULL) + return (EINVAL); + gp =3D malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); + if (uap->gidsetsize) { + iset =3D malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK); error =3D copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * uap->gidsetsize); - if (error) - return (error); + if (error) { + free(iset, M_TEMP); + goto out; + } for (i =3D 0; i < uap->gidsetsize; i++) gp[i] =3D (gid_t)iset[i]; } - return (kern_setgroups(td, uap->gidsetsize, gp)); + + error =3D kern_setgroups(td, uap->gidsetsize, gp); +out: + free(gp, M_TEMP); + return (error); } =20 int diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/kern/kern_exec.c ./sys/kern/ker= n_exec.c --- /usr/fsvn/head/sys/kern/kern_exec.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_exec.c 2009-06-12 01:13:11.000000000 -0500 @@ -579,6 +579,7 @@ * reset. */ PROC_LOCK(p); + oldcred =3D crcopysafe(p, newcred); if (sigacts_shared(p->p_sigacts)) { oldsigacts =3D p->p_sigacts; PROC_UNLOCK(p); @@ -629,7 +630,6 @@ * XXXMAC: For the time being, use NOSUID to also prohibit * transitions on the file system. */ - oldcred =3D p->p_ucred; credential_changing =3D 0; credential_changing |=3D (attr.va_mode & S_ISUID) && oldcred->cr_uid !=3D attr.va_uid; @@ -683,7 +683,6 @@ /* * Set the new credentials. */ - crcopy(newcred, oldcred); if (attr.va_mode & S_ISUID) change_euid(newcred, euip); if (attr.va_mode & S_ISGID) @@ -723,7 +722,6 @@ */ if (oldcred->cr_svuid !=3D oldcred->cr_uid || oldcred->cr_svgid !=3D oldcred->cr_gid) { - crcopy(newcred, oldcred); change_svuid(newcred, newcred->cr_uid); change_svgid(newcred, newcred->cr_gid); p->p_ucred =3D newcred; diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/kern/kern_proc.c ./sys/kern/ker= n_proc.c --- /usr/fsvn/head/sys/kern/kern_proc.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_proc.c 2009-06-05 16:02:28.000000000 -0500 @@ -730,10 +730,8 @@ kp->ki_uid =3D cred->cr_uid; kp->ki_ruid =3D cred->cr_ruid; kp->ki_svuid =3D cred->cr_svuid; - /* XXX bde doesn't like KI_NGROUPS */ - kp->ki_ngroups =3D min(cred->cr_ngroups, KI_NGROUPS); - bcopy(cred->cr_groups, kp->ki_groups, - kp->ki_ngroups * sizeof(gid_t)); + kp->ki_ngroups =3D cred->cr_ngroups; + kp->ki_groups =3D cred->cr_groups; kp->ki_rgid =3D cred->cr_rgid; kp->ki_svgid =3D cred->cr_svgid; kp->ki_cr_flags =3D cred->cr_flags; --- /usr/fsvn/head/sys/kern/kern_prot.c 2009-06-16 15:54:34.000000000 -0500 +++ ./sys/kern/kern_prot.c 2009-06-17 18:24:56.000000000 -0500 @@ -82,6 +82,10 @@ =20 SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"= ); =20 +static void crextend(struct ucred *cr, int n); +static void crsetgroups_locked(struct ucred *cr, int ngrp, + gid_t *groups); + #ifndef _SYS_SYSPROTO_H_ struct getpid_args { int dummy; @@ -276,18 +280,21 @@ int getgroups(struct thread *td, register struct getgroups_args *uap) { - gid_t groups[NGROUPS]; + gid_t *groups; u_int ngrp; int error; =20 ngrp =3D MIN(uap->gidsetsize, NGROUPS); + groups =3D malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK); error =3D kern_getgroups(td, &ngrp, groups); if (error) - return (error); + goto out; if (uap->gidsetsize > 0) error =3D copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); if (error =3D=3D 0) td->td_retval[0] =3D ngrp; +out: + free(groups, M_TEMP); return (error); } =20 @@ -486,7 +493,10 @@ newcred =3D crget(); uip =3D uifind(uid); PROC_LOCK(p); - oldcred =3D p->p_ucred; + /* + * Copy credentials so other references do not see our changes. + */ + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setuid(oldcred, uid); @@ -521,10 +531,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) !=3D 0) goto fail; =20 - /* - * Copy credentials so other references do not see our changes. - */ - crcopy(newcred, oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or uid =3D=3D euid) @@ -598,7 +604,10 @@ newcred =3D crget(); euip =3D uifind(euid); PROC_LOCK(p); - oldcred =3D p->p_ucred; + /* + * Copy credentials so other references do not see our changes. + */ + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_seteuid(oldcred, euid); @@ -612,8 +621,7 @@ goto fail; =20 /* - * Everything's okay, do it. Copy credentials so other references do - * not see our changes. + * Everything's okay, do it. */ crcopy(newcred, oldcred); if (oldcred->cr_uid !=3D euid) { @@ -651,7 +659,7 @@ AUDIT_ARG(gid, gid); newcred =3D crget(); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setgid(oldcred, gid); @@ -680,7 +688,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or gid =3D=3D egid) @@ -750,7 +757,7 @@ AUDIT_ARG(egid, egid); newcred =3D crget(); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setegid(oldcred, egid); @@ -763,7 +770,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); if (oldcred->cr_groups[0] !=3D egid) { change_egid(newcred, egid); setsugid(p); @@ -789,15 +795,19 @@ int setgroups(struct thread *td, struct setgroups_args *uap) { - gid_t groups[NGROUPS]; + gid_t *groups =3D NULL; int error; =20 if (uap->gidsetsize > NGROUPS) return (EINVAL); + groups =3D malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK); error =3D copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); if (error) - return (error); - return (kern_setgroups(td, uap->gidsetsize, groups)); + goto out; + error =3D kern_setgroups(td, uap->gidsetsize, groups); +out: + free(groups, M_TEMP); + return (error); } =20 int @@ -811,8 +821,9 @@ return (EINVAL); AUDIT_ARG(groupset, groups, ngrp); newcred =3D crget(); + crextend(newcred, ngrp); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setgroups(oldcred, ngrp, groups); @@ -824,11 +835,6 @@ if (error) goto fail; =20 - /* - * XXX A little bit lazy here. We could test if anything has - * changed before crcopy() and setting P_SUGID. - */ - crcopy(newcred, oldcred); if (ngrp < 1) { /* * setgroups(0, NULL) is a legitimate way of clearing the @@ -838,8 +844,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; @@ -877,7 +882,7 @@ euip =3D uifind(euid); ruip =3D uifind(ruid); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setreuid(oldcred, ruid, euid); @@ -892,7 +897,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); if (euid !=3D (uid_t)-1 && oldcred->cr_uid !=3D euid) { change_euid(newcred, euip); setsugid(p); @@ -942,7 +946,7 @@ AUDIT_ARG(rgid, rgid); newcred =3D crget(); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setregid(oldcred, rgid, egid); @@ -957,7 +961,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); if (egid !=3D (gid_t)-1 && oldcred->cr_groups[0] !=3D egid) { change_egid(newcred, egid); setsugid(p); @@ -1013,7 +1016,7 @@ euip =3D uifind(euid); ruip =3D uifind(ruid); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setresuid(oldcred, ruid, euid, suid); @@ -1033,7 +1036,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); if (euid !=3D (uid_t)-1 && oldcred->cr_uid !=3D euid) { change_euid(newcred, euip); setsugid(p); @@ -1090,7 +1092,7 @@ AUDIT_ARG(sgid, sgid); newcred =3D crget(); PROC_LOCK(p); - oldcred =3D p->p_ucred; + oldcred =3D crcopysafe(p, newcred); =20 #ifdef MAC error =3D mac_cred_check_setresgid(oldcred, rgid, egid, sgid); @@ -1110,7 +1112,6 @@ (error =3D priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) !=3D 0) goto fail; =20 - crcopy(newcred, oldcred); if (egid !=3D (gid_t)-1 && oldcred->cr_groups[0] !=3D egid) { change_egid(newcred, egid); setsugid(p); @@ -1780,6 +1781,7 @@ #ifdef MAC mac_cred_init(cr); #endif + crextend(cr, XU_NGROUPS); return (cr); } =20 @@ -1829,6 +1831,7 @@ #ifdef MAC mac_cred_destroy(cr); #endif + free(cr->cr_groups, M_CRED); free(cr, M_CRED); } } @@ -1854,6 +1857,7 @@ bcopy(&src->cr_startcopy, &dest->cr_startcopy, (unsigned)((caddr_t)&src->cr_endcopy - (caddr_t)&src->cr_startcopy)); + crsetgroups(dest, src->cr_ngroups, src->cr_groups); uihold(dest->cr_uidinfo); uihold(dest->cr_ruidinfo); prison_hold(dest->cr_prison); @@ -1888,12 +1892,16 @@ void cru2x(struct ucred *cr, struct xucred *xcr) { + int ngroups; =20 bzero(xcr, sizeof(*xcr)); xcr->cr_version =3D XUCRED_VERSION; xcr->cr_uid =3D cr->cr_uid; - xcr->cr_ngroups =3D cr->cr_ngroups; - bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); + + 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)); } =20 /* @@ -1915,6 +1923,97 @@ crfree(cred); } =20 +struct ucred * +crcopysafe(struct proc *p, struct ucred *cr) +{ + struct ucred *oldcred; + int groups; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + oldcred =3D p->p_ucred; + while (cr->cr_agroups < oldcred->cr_agroups) { + groups =3D oldcred->cr_agroups; + PROC_UNLOCK(p); + crextend(cr, groups); + PROC_LOCK(p); + oldcred =3D p->p_ucred; + } + crcopy(cr, oldcred); + + return (oldcred); +} + +/* + * Extend the passed in credential to hold n items. + */ +static void +crextend(struct ucred *cr, int n) +{ + int cnt; + + /* Truncate? */ + if (n <=3D cr->cr_agroups) + return; + + /* + * We extend by 2 each time since we're using a power of two + * allocator until we need enough groups to fill a page. + * Once we're allocating multiple pages, only allocate as many + * as we actually need. The case of processes needing a + * non-power of two number of pages seems more likely than + * a real world process that adds thousands of groups one at a + * time. + */ + if ( n < PAGE_SIZE / sizeof(gid_t) ) { + if (cr->cr_agroups =3D=3D 0) + cnt =3D MINALLOCSIZE / sizeof(gid_t); + else + cnt =3D cr->cr_agroups * 2; + + while (cnt < n) + cnt *=3D 2; + } else + cnt =3D roundup2(n, PAGE_SIZE / sizeof(gid_t)); + + /* Free the old array. */ + if (cr->cr_groups) + free(cr->cr_groups, M_CRED); + + cr->cr_groups =3D malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); + cr->cr_agroups =3D cnt; +} + +/* + * 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 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. */ diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/kern/vfs_export.c ./sys/kern/vf= s_export.c --- /usr/fsvn/head/sys/kern/vfs_export.c 2009-05-29 12:48:02.000000000 -0500 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/netinet/ipfw/ip_fw2.c ./sys/net= inet/ipfw/ip_fw2.c --- /usr/fsvn/head/sys/netinet/ipfw/ip_fw2.c 2009-06-12 00:52:26.000000000 = -0500 +++ ./sys/netinet/ipfw/ip_fw2.c 2009-06-17 13:42:23.000000000 -0500 @@ -135,19 +135,6 @@ struct ip_fw *ip_fw_default_rule; =20 /* - * Data structure to cache our ucred related - * information. This structure only gets used if - * the user specified UID/GID based constraints in - * a firewall rule. - */ -struct ip_fw_ugid { - gid_t fw_groups[NGROUPS]; - int fw_ngroups; - uid_t fw_uid; - int fw_prid; -}; - -/* * list of rules for layer 3 */ #ifdef VIMAGE_GLOBALS @@ -2009,22 +1996,10 @@ return (0); } =20 -static void -fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp) -{ - struct ucred *cr; - - 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)); -} - static int check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip, - u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp, + u_int16_t src_port, struct ucred **uc, int *ugid_lookupp, struct inpcb *inp) { INIT_VNET_INET(curvnet); @@ -2032,7 +2007,6 @@ int wildcard; struct inpcb *pcb; int match; - gid_t *gp; =20 /* * Check to see if the UDP or TCP stack supplied us with @@ -2042,7 +2016,7 @@ if (inp && *ugid_lookupp =3D=3D 0) { INP_LOCK_ASSERT(inp); if (inp->inp_socket !=3D NULL) { - fill_ugid_cache(inp, ugp); + *uc =3D crhold(inp->inp_cred); *ugid_lookupp =3D 1; } else *ugid_lookupp =3D -1; @@ -2075,7 +2049,7 @@ dst_ip, htons(dst_port), wildcard, NULL); if (pcb !=3D NULL) { - fill_ugid_cache(pcb, ugp); + *uc =3D crhold(inp->inp_cred); *ugid_lookupp =3D 1; } INP_INFO_RUNLOCK(pi); @@ -2091,16 +2065,11 @@ } }=20 if (insn->o.opcode =3D=3D O_UID) - match =3D (ugp->fw_uid =3D=3D (uid_t)insn->d[0]); - else if (insn->o.opcode =3D=3D O_GID) { - for (gp =3D ugp->fw_groups; - gp < &ugp->fw_groups[ugp->fw_ngroups]; gp++) - if (*gp =3D=3D (gid_t)insn->d[0]) { - match =3D 1; - break; - } - } else if (insn->o.opcode =3D=3D O_JAIL) - match =3D (ugp->fw_prid =3D=3D (int)insn->d[0]); + match =3D ((*uc)->cr_uid =3D=3D (uid_t)insn->d[0]); + else if (insn->o.opcode =3D=3D O_GID) + match =3D groupmember((gid_t)insn->d[0], *uc); + else if (insn->o.opcode =3D=3D O_JAIL) + match =3D ((*uc)->cr_prison->pr_id =3D=3D (int)insn->d[0]); return match; } =20 @@ -2178,8 +2147,8 @@ * these types of constraints, as well as decrease contention * on pcb related locks. */ - struct ip_fw_ugid fw_ugid_cache; - int ugid_lookup =3D 0; + struct ucred *ucred_cache =3D NULL; + int ucred_lookup =3D 0; =20 /* * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG @@ -2641,8 +2610,8 @@ (ipfw_insn_u32 *)cmd, proto, oif, dst_ip, dst_port, - src_ip, src_port, &fw_ugid_cache, - &ugid_lookup, args->inp); + src_ip, src_port, &ucred_cache, + &ucred_lookup, args->inp); break; =20 case O_RECV: @@ -3270,6 +3239,8 @@ /* XXX statistic */ /* drop packet */ IPFW_RUNLOCK(chain); + if (ucred_cache !=3D NULL) + crfree(ucred_cache); return (IP_FW_DENY); } dt =3D (struct divert_tag *)(mtag+1); @@ -3475,6 +3446,8 @@ } /* end of outer for, scan rules */ printf("ipfw: ouch!, skip past end of rules, denying packet\n"); IPFW_RUNLOCK(chain); + if (ucred_cache !=3D NULL) + crfree(ucred_cache); return (IP_FW_DENY); =20 done: @@ -3483,6 +3456,8 @@ f->bcnt +=3D pktlen; f->timestamp =3D time_uptime; IPFW_RUNLOCK(chain); + if (ucred_cache !=3D NULL) + crfree(ucred_cache); return (retval); =20 pullup_failed: diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/nfsserver/nfs_srvsock.c ./sys/n= fsserver/nfs_srvsock.c --- /usr/fsvn/head/sys/nfsserver/nfs_srvsock.c 2009-06-16 15:54:40.00000000= 0 -0500 +++ ./sys/nfsserver/nfs_srvsock.c 2009-06-09 08:49:37.000000000 -0500 @@ -370,11 +370,11 @@ } tl =3D nfsm_dissect_nonblock(u_int32_t *, (len + 2) * NFSX_UNSIGNED); for (i =3D 1; i <=3D len; i++) - if (i < NGROUPS) + if (i < XU_NGROUPS) nd->nd_cr->cr_groups[i] =3D fxdr_unsigned(gid_t, *tl++); else tl++; - nd->nd_cr->cr_ngroups =3D (len >=3D NGROUPS) ? 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); diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/nfsserver/nfs_srvsubs.c ./sys/n= fsserver/nfs_srvsubs.c --- /usr/fsvn/head/sys/nfsserver/nfs_srvsubs.c 2009-05-29 12:48:04.00000000= 0 -0500 +++ ./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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c= ./sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- /usr/fsvn/head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-16 13:55:57.= 000000000 -0500 +++ ./sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2009-06-16 13:56:18.000000000 -05= 00 @@ -449,11 +449,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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/rpc/svc_auth.c ./sys/rpc/svc_au= th.c --- /usr/fsvn/head/sys/rpc/svc_auth.c 2009-06-12 00:52:17.000000000 -0500 +++ ./sys/rpc/svc_auth.c 2009-06-12 01:13:12.000000000 -0500 @@ -166,7 +166,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; @@ -178,9 +178,7 @@ 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]; + crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); cr->cr_rgid =3D cr->cr_svgid =3D cr->cr_groups[0]; cr->cr_prison =3D &prison0; prison_hold(cr->cr_prison); diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/rpc/svc_auth_unix.c ./sys/rpc/s= vc_auth_unix.c --- /usr/fsvn/head/sys/rpc/svc_auth_unix.c 2009-01-22 10:05:57.000000000 -0= 600 +++ ./sys/rpc/svc_auth_unix.c 2009-06-09 08:49:37.000000000 -0500 @@ -95,13 +95,13 @@ 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.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/sys/param.h ./sys/sys/param.h --- /usr/fsvn/head/sys/sys/param.h 2009-06-16 13:55:59.000000000 -0500 +++ ./sys/sys/param.h 2009-06-16 13:56:20.000000000 -0500 @@ -77,7 +77,7 @@ #define MAXLOGNAME 17 /* max login name length (incl. NUL) */ #define MAXUPRC CHILD_MAX /* max simultaneous processes */ #define NCARGS ARG_MAX /* max bytes for an exec function */ -#define NGROUPS NGROUPS_MAX /* max number groups */ +#define NGROUPS NGROUPS_MAX+1 /* max number groups */ #define NOFILE OPEN_MAX /* max open files per process */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */ diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/sys/syslimits.h ./sys/sys/sysli= mits.h --- /usr/fsvn/head/sys/sys/syslimits.h 2009-01-22 10:06:22.000000000 -0600 +++ ./sys/sys/syslimits.h 2009-06-08 23:57:36.000000000 -0500 @@ -54,7 +54,9 @@ #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 */ +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 1023 /* max supplemental group id's */ +#endif #ifndef OPEN_MAX #define OPEN_MAX 64 /* max open files per process */ #endif --- /usr/fsvn/head/sys/sys/ucred.h 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/sys/ucred.h 2009-06-17 18:23:49.000000000 -0500 @@ -48,8 +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 */ - gid_t cr_groups[NGROUPS]; /* 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,11 +60,15 @@ #define cr_endcopy cr_label struct label *cr_label; /* MAC label */ struct auditinfo_addr cr_audit; /* Audit properties. */ + gid_t *cr_groups; /* groups */ + int cr_agroups; /* Available groups */ }; #define NOCRED ((struct ucred *)0) /* no credential available */ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #endif /* _KERNEL || _WANT_UCRED */ =20 +#define XU_NGROUPS 16 + /* * This is the external representation of struct ucred. */ @@ -73,7 +76,7 @@ u_int cr_version; /* structure layout version */ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ - gid_t cr_groups[NGROUPS]; /* groups */ + gid_t cr_groups[XU_NGROUPS]; /* groups */ void *_cr_unused1; /* compatibility with old ucred */ }; #define XUCRED_VERSION 0 @@ -82,6 +85,7 @@ #define cr_gid cr_groups[0] =20 #ifdef _KERNEL +struct proc; struct thread; =20 void change_egid(struct ucred *newcred, gid_t egid); @@ -91,6 +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 *p, struct ucred *cr); struct ucred *crdup(struct ucred *cr); void cred_update_thread(struct thread *td); void crfree(struct ucred *cr); @@ -98,6 +103,7 @@ struct ucred *crhold(struct ucred *cr); int crshared(struct ucred *cr); void cru2x(struct ucred *cr, struct xucred *xcr); +void crsetgroups(struct ucred *cr, int n, gid_t *groups); int groupmember(gid_t gid, struct ucred *cred); #endif /* _KERNEL */ =20 diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/sys/user.h ./sys/sys/user.h --- /usr/fsvn/head/sys/sys/user.h 2009-06-16 15:54:53.000000000 -0500 +++ ./sys/sys/user.h 2009-06-05 16:02:34.000000000 -0500 @@ -85,7 +85,7 @@ */ #define KI_NSPARE_INT 9 #define KI_NSPARE_LONG 12 -#define KI_NSPARE_PTR 7 +#define KI_NSPARE_PTR 6 =20 #ifdef __amd64__ #define KINFO_PROC_SIZE 1088 @@ -117,7 +117,6 @@ #define OCOMMLEN 16 /* size of returned thread name */ #define COMMLEN 19 /* size of returned ki_comm name */ #define KI_EMULNAMELEN 16 /* size of returned ki_emul */ -#define KI_NGROUPS 16 /* number of groups in ki_groups */ #define LOGNAMELEN 17 /* size of returned ki_login */ =20 struct kinfo_proc { @@ -151,7 +150,7 @@ gid_t ki_svgid; /* Saved effective group id */ short ki_ngroups; /* number of groups */ short ki_spare_short2; /* unused (just here for alignment) */ - gid_t ki_groups[KI_NGROUPS]; /* groups */ + uint32_t __was_ki_groups[16]; /* unused; left for bin compat */ vm_size_t ki_size; /* virtual size */ segsz_t ki_rssize; /* current resident set size in pages */ segsz_t ki_swrss; /* resident set size before last swap */ @@ -201,6 +200,7 @@ struct pcb *ki_pcb; /* kernel virtual addr of pcb */ void *ki_kstack; /* kernel virtual addr of stack */ void *ki_udata; /* User convenience pointer */ + gid_t *ki_groups; /* groups */ /* * When adding new variables, take space for pointers from the * front of ki_spareptrs, and longs from the end of ki_sparelongs. diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/sys/ufs/ufs/ufs_vnops.c ./sys/ufs/u= fs/ufs_vnops.c --- /usr/fsvn/head/sys/ufs/ufs/ufs_vnops.c 2009-06-16 13:55:57.000000000 -0= 500 +++ ./sys/ufs/ufs/ufs_vnops.c 2009-06-16 13:56:20.000000000 -0500 @@ -2266,6 +2266,7 @@ { #ifdef QUOTA struct ucred ucred, *ucp; + gid_t ucred_group; ucp =3D cnp->cn_cred; #endif /* @@ -2292,6 +2293,7 @@ refcount_init(&ucred.cr_ref, 1); ucred.cr_uid =3D ip->i_uid; ucred.cr_ngroups =3D 1; + ucred.cr_groups =3D &ucred_group; ucred.cr_groups[0] =3D pdir->i_gid; ucp =3D &ucred; #endif diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/mount_portalfs/portald.h .= /usr.sbin/mount_portalfs/portald.h --- /usr/fsvn/head/usr.sbin/mount_portalfs/portald.h 2009-01-22 10:05:31.00= 0000000 -0600 +++ ./usr.sbin/mount_portalfs/portald.h 2009-06-17 13:41:26.000000000 -0500 @@ -36,6 +36,7 @@ */ =20 #include +#include #include =20 /* diff -ru --exclude=3D.svn --exclude=3Dcompile --exclude=3Dcardbus.c --ignor= e-matching=3D'$FreeBSD:' /usr/fsvn/head/usr.sbin/mountd/mountd.c ./usr.sbin= /mountd/mountd.c --- /usr/fsvn/head/usr.sbin/mountd/mountd.c 2009-06-16 15:54:05.000000000 -= 0500 +++ ./usr.sbin/mountd/mountd.c 2009-06-17 15:25:33.000000000 -0500 @@ -2644,7 +2644,7 @@ char *names; struct passwd *pw; struct group *gr; - gid_t groups[NGROUPS + 1]; + gid_t groups[XU_NGROUPS + 1]; int ngroups; =20 cr->cr_version =3D XUCRED_VERSION; @@ -2672,7 +2672,7 @@ return; } cr->cr_uid =3D pw->pw_uid; - ngroups =3D NGROUPS + 1; + ngroups =3D XU_NGROUPS + 1; if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) syslog(LOG_ERR, "too many groups"); /* @@ -2697,7 +2697,7 @@ return; } cr->cr_ngroups =3D 0; - while (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups < NGROUPS) { + while (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups < XU_NGROUPS= ) { name =3D strsep(&names, ":"); if (isdigit(*name) || *name =3D=3D '-') { cr->cr_groups[cr->cr_ngroups++] =3D atoi(name); @@ -2709,7 +2709,7 @@ cr->cr_groups[cr->cr_ngroups++] =3D gr->gr_gid; } } - if (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups =3D=3D NGROUPS) + if (names !=3D NULL && *names !=3D '\0' && cr->cr_ngroups =3D=3D XU_NGROU= PS) syslog(LOG_ERR, "too many groups"); } =20 --YZ5djTAD1cGYuMQK-- --O5XBE6gyVG5Rl6Rj Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iD8DBQFKOYTKXY6L6fI4GtQRAoiYAJ9BzCBNbP/75Un8IE0lnANi+vLzcACgvb3y Qn1aK6Ca1A8ZeOXWFkULVJo= =wA9V -----END PGP SIGNATURE----- --O5XBE6gyVG5Rl6Rj--