diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/lib/libc/gen/initgroups.3 ./lib/libc/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=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/lib/libc/gen/initgroups.c ./lib/libc/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 @@ #include -#include #include "namespace.h" #include #include "un-namespace.h" +#include +#include +#include #include 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 = sysconf(_SC_NGROUPS_MAX) + 2; + if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL) + return (ENOMEM); - ngroups = NGROUPS + 1; + ngroups = (int)ngroups_max; getgrouplist(uname, agroup, groups, &ngroups); - return (setgroups(ngroups, groups)); + ret = setgroups(ngroups, groups); + free(groups); + return (ret); } diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$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 = sysconf(_SC_NGROUPS_MAX) + 1; + gids = malloc(sizeof(gid_t) * ngids_max); + if (gids == NULL) + return (NULL); if (gethostname(machname, sizeof machname) == -1) abort(); machname[sizeof(machname) - 1] = 0; uid = geteuid(); gid = getegid(); - if ((len = getgroups(NGROUPS_MAX, gids)) < 0) + if ((ngids = getgroups(ngids_max, gids)) < 0) abort(); - if (len > NGRPS) - len = NGRPS; + if (ngids > NGRPS) + ngids = 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)); } diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$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=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$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=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$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; if (pw != NULL) { @@ -270,12 +271,16 @@ gid = getgid(); } + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); + if (use_ggl && pw != NULL) { - ngroups = NGROUPS + 1; + ngroups = ngroups_max; getgrouplist(pw->pw_name, gid, groups, &ngroups); } else { - ngroups = getgroups(NGROUPS + 1, groups); + ngroups = getgroups(ngroups_max, groups); } if (pw != NULL) @@ -306,6 +311,7 @@ lastgid = gid; } printf("\n"); + free(groups); } #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; + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL) + err(1, "malloc"); + if (pw) { - ngroups = NGROUPS + 1; + ngroups = ngroups_max; (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); } else { - groups[0] = getgid(); - ngroups = getgroups(NGROUPS, groups + 1) + 1; + ngroups = getgroups(ngroups_max, groups); } fmt = nflag ? "%s" : "%u"; for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) { @@ -389,6 +399,7 @@ lastid = id; } (void)printf("\n"); + free(groups); } void diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.bin/newgrp/newgrp.c ./usr.bin/newgrp/newgrp.c --- /usr/fsvn/head/usr.bin/newgrp/newgrp.c 2009-01-22 10:04:11.000000000 -0600 +++ ./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 @@ } } - if ((ngrps = getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) { + ngrps_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((grps = malloc(sizeof(gid_t) * ngrps_max)) == NULL) + err(1, "malloc"); + if ((ngrps = getgroups(ngrps_max, (gid_t *)grps)) < 0) { warn("getgroups"); return; } @@ -217,7 +220,7 @@ /* Add old effective gid to supp. list if it does not exist. */ if (egid != grp->gr_gid && !inarray(egid, grps, ngrps)) { - if (ngrps == NGROUPS_MAX) + if (ngrps == ngrps_max) warnx("too many groups"); else { grps[ngrps++] = egid; @@ -231,6 +234,7 @@ } } + free(grps); } static int diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.bin/quota/quota.c ./usr.bin/quota/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; - gid_t mygid, gidset[NGROUPS]; + long ngroups_max; + gid_t mygid, *gidset; int i, ch, gflag = 0, uflag = 0, errflag = 0; while ((ch = getopt(argc, argv, "f:ghlrquv")) != -1) { @@ -159,13 +160,18 @@ errflag += showuid(getuid()); if (gflag) { mygid = getgid(); - ngroups = getgroups(NGROUPS, gidset); + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((gidset = malloc(sizeof(gid_t) * ngroups_max)) + == NULL) + err(1, "malloc"); + ngroups = getgroups(ngroups_max, gidset); if (ngroups < 0) err(1, "getgroups"); errflag += showgid(mygid); for (i = 0; i < ngroups; i++) if (gidset[i] != mygid) errflag += showgid(gidset[i]); + free(gidset); } return(errflag); } diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/chown/chown.c ./usr.sbin/chown/chown.c --- /usr/fsvn/head/usr.sbin/chown/chown.c 2009-01-22 10:05:31.000000000 -0600 +++ ./usr.sbin/chown/chown.c 2009-06-17 14:00:59.000000000 -0500 @@ -269,7 +269,8 @@ { static uid_t euid = -1; static int ngroups = -1; - gid_t groups[NGROUPS_MAX]; + static long ngroups_max; + gid_t *groups; /* Check for chown without being root. */ if (errno != EPERM || (uid != (uid_t)-1 && @@ -281,7 +282,10 @@ /* Check group membership; kernel just returns EPERM. */ if (gid != (gid_t)-1 && ngroups == -1 && euid == (uid_t)-1 && (euid = geteuid()) != 0) { - ngroups = getgroups(NGROUPS_MAX, groups); + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); + ngroups = getgroups(ngroups_max, groups); while (--ngroups >= 0 && gid != groups[ngroups]); if (ngroups < 0) { warnx("you are not a member of group %s", gname); diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$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; gid = 0; uid = 0; @@ -117,8 +118,11 @@ } } + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); for (gids = 0; - (p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX; ) { + (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) { if (*p == '\0') continue; @@ -135,7 +139,7 @@ } gids++; } - if (p != NULL && gids == NGROUPS_MAX) + if (p != NULL && gids == ngroups_max) errx(1, "too many supplementary groups provided"); if (user != NULL) { diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/jail/jail.c ./usr.sbin/jail/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 = login_getpwclass(pwd); \ if (lcap == NULL) \ err(1, "getpwclass: %s", username); \ - ngroups = NGROUPS; \ + ngroups = ngroups_max; \ if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ err(1, "getgrouplist: %s", username); \ } while (0) @@ -115,10 +115,11 @@ login_cap_t *lcap = NULL; struct iovec rparams[2]; struct passwd *pwd = 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 = securelevel = username = JidFile = cleanenv = NULL; fp = NULL; + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); + while ((ch = getopt(argc, argv, "cdhilmn:r:s:u:U:J:")) != -1) { switch (ch) { case 'd': diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/jexec/jexec.c ./usr.sbin/jexec/jexec.c --- /usr/fsvn/head/usr.sbin/jexec/jexec.c 2009-05-29 12:48:00.000000000 -0500 +++ ./usr.sbin/jexec/jexec.c 2009-06-17 14:00:59.000000000 -0500 @@ -59,7 +59,7 @@ lcap = login_getpwclass(pwd); \ if (lcap == NULL) \ err(1, "getpwclass: %s", username); \ - ngroups = NGROUPS; \ + ngroups = ngroups_max; \ if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ err(1, "getgrouplist: %s", username); \ } while (0) @@ -71,12 +71,17 @@ int jid; login_cap_t *lcap = NULL; struct passwd *pwd = NULL; - gid_t groups[NGROUPS]; + gid_t *groups = NULL; int ch, ngroups, uflag, Uflag; + long ngroups_max; char *ep, *username; ch = uflag = Uflag = 0; username = NULL; + ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; + if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); + while ((ch = getopt(argc, argv, "nu:U:")) != -1) { switch (ch) { case 'n': diff -ru --exclude=.svn --exclude=compile --exclude=cardbus.c --ignore-matching='$FreeBSD:' /usr/fsvn/head/usr.sbin/lpr/lpc/lpc.c ./usr.sbin/lpr/lpc/lpc.c --- /usr/fsvn/head/usr.sbin/lpr/lpc/lpc.c 2009-01-22 10:05:32.000000000 -0600 +++ ./usr.sbin/lpr/lpc/lpc.c 2009-06-17 14:00:59.000000000 -0500 @@ -356,7 +356,8 @@ { static struct group *gptr=NULL; static int ngroups = 0; - static gid_t groups[NGROUPS]; + static long ngroups_max; + static gid_t *groups; register gid_t gid; register int i; @@ -365,7 +366,10 @@ warnx("warning: unknown group '%s'", grname); return(0); } - ngroups = getgroups(NGROUPS, groups); + ngroups_max = sysconf(_SC_NGROUPS_MAX); + if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) + err(1, "malloc"); + ngroups = getgroups(ngroups_max, groups); if (ngroups < 0) err(1, "getgroups"); }