Date: Tue, 24 Mar 2009 11:09:26 +0000 From: n0g0013 <ttw+bsd@cobbled.net> To: Boris Kochergin <spawk@acm.poly.edu> Cc: freebsd-hackers@freebsd.org Subject: Re: Doing away with NGROUPS_MAX in src/sys/sys/syslimits.h? Message-ID: <20090324110926.GA14099@holyman.cobbled.net> In-Reply-To: <49C7B793.1090308@acm.poly.edu> References: <49C6F4F4.5030609@acm.poly.edu> <20090323124502.GA8686@holyman.cobbled.net> <49C79A9B.9070309@acm.poly.edu> <20090323155433.GA24517@holyman.cobbled.net> <49C7B793.1090308@acm.poly.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
--zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On 23.03-12:23, Boris Kochergin wrote: [ ... ] > >yes, that's great but you may be surprised to learn that it doesn't > >actually solve your problem. i think (and without looking > >specifically at the impact my even be confident enough to say > >definately) if you get a groups list it will only be cropped and the > >error message is being erroneously avoided, not corrected. i'd also > >suggest that you may be opening up your system to some overflows > >although, generally, the code sections use the same limits and so > >you might get away with it. [ ... ] > On my 7.0 system, and a kernel recompiled with NGROUPS_MAX set to 64, a > getgrouplist() call for a user who is in more than 16 groups (24, to be > exact) will populate the array specified by the "gid_t *groups" argument > with the 24 groups the user is in, in addition to the group specified in > the "gid_t basegid" argument. The value of the variable specified in the > "int *ngroups" will also be 25, and the getgrouplist() call will return > 0. So, as far as being a hack for a specific problem, it seems to work > properly. yeah, looked at it now. NGROUPS is defined from NGROUPS_MAX (bad memory). the other significant values would be KI_NGROUPS which is not defined from NGROUPS_MAX; neither are the IPC or RPC relevant values, although, as i said they use their own max values for validation (i.e. they don't suddenly using NGROUPS_MAX instead of CMGROUPS) so probably won't overflow trivially but i wouldn't say they are necissarily safe. suffice to say if it works for you great but be aware that you may have security and other issues associated with the change. [ ... ] > Sure, I'll test the patch. Can you point me at it? sure, attached. but note it's functionally zero progress, it only looks to remove the dependancy on NGROUPS_MAX as static definition and make SC_NGROUPS_MAX a writable and referenced value. however, it won't currently give you the extra groups you want because it defines other values from _NGROUP_COMPAT (which is 16) until i can complete the changes to a stable state. it would still be nice to know that i haven't messed it up completely and that, at the very least the system still boots and runs with it. p.s: i've gotta finish some bloody web stuff and then i'll throw some more time at it this afternoon. -- t t w --zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="remove-ngroups_max,v1r2.patch" Index: contrib/openpam/lib/openpam_borrow_cred.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/contrib/openpam/lib/openpam_borrow_cred.c,v retrieving revision 1.1.1.9 diff -b -u -r1.1.1.9 openpam_borrow_cred.c --- contrib/openpam/lib/openpam_borrow_cred.c 21 Dec 2007 11:49:29 -0000 1.1.1.9 +++ contrib/openpam/lib/openpam_borrow_cred.c 4 Feb 2009 16:38:46 -0000 @@ -60,6 +60,7 @@ struct pam_saved_cred *scred; const void *scredp; int r; + int ngroups ; ENTERI(pwd->pw_uid); r = pam_get_data(pamh, PAM_SAVED_CRED, &scredp); @@ -73,26 +74,55 @@ (int)geteuid()); RETURNC(PAM_PERM_DENIED); } - scred = calloc(1, sizeof *scred); - if (scred == NULL) - RETURNC(PAM_BUF_ERR); - scred->euid = geteuid(); - scred->egid = getegid(); - r = getgroups(NGROUPS_MAX, scred->groups); - if (r < 0) { - FREE(scred); - RETURNC(PAM_SYSTEM_ERR); - } - scred->ngroups = r; +/* get the maximum number of system groups */ +#if _POSIX_VERSION > 199212 + ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + ngroups = NGROUPS_MAX ; +#else + ngroups = _NGROUPS_COMPAT ; +#endif +/* initally allocate enough memory for max_groups */ + scred = malloc( sizeof(struct pam_saved_cred) + + ngroups*sizeof(gid_t) ) ; + if( scred == NULL ) + RETURNC( PAM_BUF_ERR ) ; +/* set the save values */ + scred->euid = geteuid() ; + scred->egid = getegid() ; +/* save groups into our (probably) oversized memory allocation */ + r = getgroups( ngroups, scred->groups ) ; + if( r < 0 ) { + FREE( scred ) ; /* call PAM's free macro */ + RETURNC( PAM_SYSTEM_ERR ) ; + } ; + scred->ngroups = r ; + ngroups = r < ngroups ? r : ngroups ; /* choose the smallest */ + /* ... number of groups to allocate */ + ngroups = ngroups < _NGROUPS_COMPAT ? ngroups : _NGROUPS_COMPAT ; + /* but keep it within expected minimum value */ + /* XXX: we don't really want this but until we get + * educated on the implications this is probably safe + * and certainaly compatible */ +/* realloc, releasing unneeded memory */ + scred = realloc( (void*)scred, + sizeof(struct pam_saved_cred)+ngroups*sizeof(gid_t) ) ; + /* nb: we ignore failure and try to store the larger + * ... structure as initially requested. catching the + * ... error in 'pam_set_data' if neccessary. */ +/* save the credentials to PAM user data area */ r = pam_set_data(pamh, PAM_SAVED_CRED, scred, &openpam_free_data); if (r != PAM_SUCCESS) { FREE(scred); RETURNC(r); } +/* set the new credentials */ if (geteuid() == pwd->pw_uid) RETURNC(PAM_SUCCESS); if (initgroups(pwd->pw_name, pwd->pw_gid) < 0 || - setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0) { + setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0) + { + /* if any of the set calls failed, then restore and fail */ openpam_restore_cred(pamh); RETURNC(PAM_SYSTEM_ERR); } Index: contrib/openpam/lib/openpam_impl.h =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/contrib/openpam/lib/openpam_impl.h,v retrieving revision 1.1.1.17 diff -b -u -r1.1.1.17 openpam_impl.h --- contrib/openpam/lib/openpam_impl.h 21 Dec 2007 11:49:29 -0000 1.1.1.17 +++ contrib/openpam/lib/openpam_impl.h 5 Feb 2009 15:41:19 -0000 @@ -110,13 +110,17 @@ int env_size; }; -#ifdef NGROUPS_MAX +#if _POSIX_VERSION > 199212 #define PAM_SAVED_CRED "pam_saved_cred" struct pam_saved_cred { uid_t euid; gid_t egid; - gid_t groups[NGROUPS_MAX]; int ngroups; + gid_t groups[]; + /* keep this last so that we can simply + .. over-allocate the amount of space + .. nb: don't use sizeof' unless you adjust + .. for the number of groups */ }; #endif Index: include/rpc/auth_unix.h =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/include/rpc/auth_unix.h,v retrieving revision 1.11 diff -b -u -r1.11 auth_unix.h --- include/rpc/auth_unix.h 23 Mar 2002 17:24:55 -0000 1.11 +++ include/rpc/auth_unix.h 14 Jan 2009 11:15:21 -0000 @@ -52,7 +52,7 @@ #define MAX_MACHINE_NAME 255 /* gids compose part of a credential; there may not be more than 16 of them */ -#define NGRPS 16 +#define AUTH_UNIX_NGROUPS 16 /* * Unix style credentials. Index: lib/libc/rpc/auth_unix.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/auth_unix.c,v retrieving revision 1.18 diff -b -u -r1.18 auth_unix.c --- lib/libc/rpc/auth_unix.c 14 Jun 2007 20:07:35 -0000 1.18 +++ lib/libc/rpc/auth_unix.c 4 Feb 2009 15:31:57 -0000 @@ -182,27 +182,48 @@ * Returns an auth handle with parameters determined by doing lots of * syscalls. */ -AUTH * +AUTH* authunix_create_default() { - int len; char machname[MAXHOSTNAMELEN + 1]; + AUTH* auth_unix ; uid_t uid; gid_t gid; - gid_t gids[NGROUPS_MAX]; - - if (gethostname(machname, sizeof machname) == -1) - abort(); - machname[sizeof(machname) - 1] = 0; + gid_t *gids ; + uint ngroups ; + uint max_ngroups ; + +/* get hostname or fail */ + if( gethostname(machname,sizeof(machname)) == -1 ) + abort() ; + machname[sizeof(machname)-1] = 0 ; /* add a null terminator */ +/* set uid/gid from current effective values */ uid = geteuid(); gid = getegid(); - if ((len = getgroups(NGROUPS_MAX, gids)) < 0) - abort(); - if (len > NGRPS) - len = NGRPS; - /* XXX: interface problem; those should all have been unsigned */ - return (authunix_create(machname, (int)uid, (int)gid, len, - (int *)gids)); +/* set the group set */ +#if _POSIX_VERSION > 199212 + max_ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_ngroups = NGROUPS_MAX ; +#else + max_ngroups = 16 ; +#endif + gids = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ; + if( gids == NULL ) + abort () ; + if( (ngroups=getgroups(max_ngroups,gids)) < 0 ) { + free( gids ) ; + abort() ; + } +/* clip the groups to a transmissable size */ + if( ngroups > AUTH_UNIX_NGROUPS ) + ngroups = AUTH_UNIX_NGROUPS ; +/* XXX: interface problem; those should all have been unsigned */ + auth_unix = authunix_create( machname, + (int)uid, (int)gid, (int)ngroups, + (int*)gids ) ; + free( (void*)gids ) ; + return( auth_unix ) ; } /* Index: lib/libc/rpc/authunix_prot.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/authunix_prot.c,v retrieving revision 1.10 diff -b -u -r1.10 authunix_prot.c --- lib/libc/rpc/authunix_prot.c 20 Nov 2007 01:51:20 -0000 1.10 +++ lib/libc/rpc/authunix_prot.c 4 Feb 2009 16:03:29 -0000 @@ -67,13 +67,14 @@ paup_gids = &p->aup_gids; - if (xdr_u_long(xdrs, &(p->aup_time)) - && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) - && xdr_int(xdrs, &(p->aup_uid)) - && xdr_int(xdrs, &(p->aup_gid)) - && xdr_array(xdrs, (char **) paup_gids, - &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) { - return (TRUE); + if( xdr_u_long(xdrs,&(p->aup_time)) && + xdr_string(xdrs,&(p->aup_machname),MAX_MACHINE_NAME) && + xdr_int(xdrs,&(p->aup_uid)) && + xdr_int(xdrs,&(p->aup_gid)) && + xdr_array(xdrs,(char**)paup_gids,&(p->aup_len), + AUTH_UNIX_NGROUPS,sizeof(int),(xdrproc_t)xdr_int) ) + { + return( TRUE ) ; } - return (FALSE); + return( FALSE ) ; } Index: lib/libc/rpc/netname.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/netname.c,v retrieving revision 1.8 diff -b -u -r1.8 netname.c --- lib/libc/rpc/netname.c 16 Oct 2004 06:11:35 -0000 1.8 +++ lib/libc/rpc/netname.c 14 Jan 2009 01:29:47 -0000 @@ -61,6 +61,7 @@ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif + #ifndef NGROUPS #define NGROUPS 16 #endif Index: lib/libc/rpc/netnamer.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/netnamer.c,v retrieving revision 1.12 diff -b -u -r1.12 netnamer.c --- lib/libc/rpc/netnamer.c 10 Mar 2005 00:58:21 -0000 1.12 +++ lib/libc/rpc/netnamer.c 3 Feb 2009 17:55:48 -0000 @@ -69,7 +69,6 @@ #ifndef NGROUPS #define NGROUPS 16 #endif - /* * Convert network-name into unix credential */ @@ -104,7 +103,7 @@ return (0); } *gidp = (gid_t) atol(p); - for (gidlen = 0; gidlen < NGROUPS; gidlen++) { + for (gidlen = 0; gidlen < _NGROUPS_RPC_MAX; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) break; @@ -157,7 +156,7 @@ static int _getgroups(uname, groups) char *uname; - gid_t groups[NGROUPS]; + gid_t groups[_NGROUPS_RPC_MAX]; { gid_t ngroups = 0; struct group *grp; @@ -169,10 +168,11 @@ while ((grp = getgrent())) { for (i = 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups == NGROUPS) { + if( ngroups == _NGROUPS_RPC_MAX ) { #ifdef DEBUG - fprintf(stderr, - "initgroups: %s is in too many groups\n", uname); + fprintf( stderr, + "initgroups: %s is in too many groups\n", + uname ) ; #endif goto toomany; } Index: lib/libc/rpc/svc_auth_des.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/svc_auth_des.c,v retrieving revision 1.9 diff -b -u -r1.9 svc_auth_des.c --- lib/libc/rpc/svc_auth_des.c 22 Mar 2002 23:18:37 -0000 1.9 +++ lib/libc/rpc/svc_auth_des.c 3 Feb 2009 17:51:01 -0000 @@ -452,7 +452,7 @@ short uid; /* cached uid */ short gid; /* cached gid */ short grouplen; /* length of cached groups */ - short groups[NGROUPS]; /* cached groups */ + short groups[_NGROUPS_RPC_MAX]; /* cached groups */ }; /* Index: lib/libc/rpc/svc_auth_unix.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/svc_auth_unix.c,v retrieving revision 1.11 diff -b -u -r1.11 svc_auth_unix.c --- lib/libc/rpc/svc_auth_unix.c 16 Oct 2004 06:11:35 -0000 1.11 +++ lib/libc/rpc/svc_auth_unix.c 4 Feb 2009 16:04:10 -0000 @@ -68,7 +68,7 @@ struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME+1]; - int area_gids[NGRPS]; + int area_gids[AUTH_UNIX_NGROUPS] ; } *area; u_int auth_len; size_t str_len, gid_len; @@ -98,7 +98,7 @@ aup->aup_uid = (int)IXDR_GET_INT32(buf); aup->aup_gid = (int)IXDR_GET_INT32(buf); gid_len = (size_t)IXDR_GET_U_INT32(buf); - if (gid_len > NGRPS) { + if( gid_len > AUTH_UNIX_NGROUPS ) { stat = AUTH_BADCRED; goto done; } Index: lib/librpcsec_gss/svc_rpcsec_gss.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/librpcsec_gss/svc_rpcsec_gss.c,v retrieving revision 1.4 diff -b -u -r1.4 svc_rpcsec_gss.c --- lib/librpcsec_gss/svc_rpcsec_gss.c 3 Nov 2008 10:38:00 -0000 1.4 +++ lib/librpcsec_gss/svc_rpcsec_gss.c 5 Feb 2009 16:09:37 -0000 @@ -127,7 +127,7 @@ rpc_gss_ucred_t cl_ucred; /* unix-style credentials */ bool_t cl_done_callback; /* TRUE after call */ void *cl_cookie; /* user cookie from callback */ - gid_t cl_gid_storage[NGRPS]; + gid_t cl_gid_storage[AUTH_UNIX_NGROUPS]; gss_OID cl_mech; /* mechanism */ gss_qop_t cl_qop; /* quality of protection */ u_int cl_seq; /* current sequence number */ @@ -578,7 +578,7 @@ getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw); if (pw) { - int len = NGRPS; + int len = AUTH_UNIX_NGROUPS; uc->uid = pw->pw_uid; uc->gid = pw->pw_gid; uc->gidlist = client->cl_gid_storage; Index: sys/compat/svr4/svr4_misc.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/compat/svr4/svr4_misc.c,v retrieving revision 1.101 diff -b -u -r1.101 svr4_misc.c --- sys/compat/svr4/svr4_misc.c 21 Apr 2008 21:24:08 -0000 1.101 +++ sys/compat/svr4/svr4_misc.c 14 Jan 2009 11:58:47 -0000 @@ -710,7 +710,12 @@ *retval = 0; break; case SVR4_CONFIG_NGROUPS: - *retval = NGROUPS_MAX; + *retval = _NGROUPS_COMPAT; + /* XXX: this should pull the value + * from sysctl but i cannot find + * the definitions for the similar + * varaibles here (i.e. 'maxproc') + */ break; case SVR4_CONFIG_CHILD_MAX: *retval = maxproc; Index: sys/fs/portalfs/portal.h =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/fs/portalfs/portal.h,v retrieving revision 1.10 diff -b -u -r1.10 portal.h --- sys/fs/portalfs/portal.h 6 Jan 2005 18:10:40 -0000 1.10 +++ sys/fs/portalfs/portal.h 16 Jan 2009 23:44:50 -0000 @@ -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[_NGROUPS_COMPAT]; /* From ucred */ }; #ifdef _KERNEL Index: sys/i386/ibcs2/ibcs2_misc.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/i386/ibcs2/ibcs2_misc.c,v retrieving revision 1.70 diff -b -u -r1.70 ibcs2_misc.c --- sys/i386/ibcs2/ibcs2_misc.c 13 Jan 2008 14:44:07 -0000 1.70 +++ sys/i386/ibcs2/ibcs2_misc.c 14 Jan 2009 12:24:56 -0000 @@ -659,14 +659,14 @@ struct thread *td; struct ibcs2_getgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t iset[_NGROUPS_COMPAT]; + gid_t gp[_NGROUPS_COMPAT]; u_int i, ngrp; int error; if (uap->gidsetsize < 0) return (EINVAL); - ngrp = MIN(uap->gidsetsize, NGROUPS_MAX); + ngrp = MIN(uap->gidsetsize, _NGROUPS_COMPAT); error = kern_getgroups(td, &ngrp, gp); if (error) return (error); @@ -685,11 +685,11 @@ struct thread *td; struct ibcs2_setgroups_args *uap; { - ibcs2_gid_t iset[NGROUPS_MAX]; - gid_t gp[NGROUPS_MAX]; + ibcs2_gid_t iset[_NGROUPS_COMPAT]; + gid_t gp[_NGROUPS_COMPAT]; int error, i; - if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX) + if (uap->gidsetsize < 0 || uap->gidsetsize > _NGROUPS_COMPAT) return (EINVAL); if (uap->gidsetsize && uap->gidset) { error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * @@ -789,8 +789,13 @@ return 0; case IBCS2_SC_NGROUPS_MAX: - mib[1] = KERN_NGROUPS; - break; + /* XXX: IBCS2 compat with group limits not known to + * me, so i'll just return a compatibile/safe limit + * for now */ + PROC_LOCK(p) ; + td->td_retval[0] = _NGROUPS_COMPAT ; + PROC_UNLOCK(p) ; + return( 0 ) ; case IBCS2_SC_OPEN_MAX: PROC_LOCK(p); Index: sys/kern/kern_mib.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/kern/kern_mib.c,v retrieving revision 1.93 diff -b -u -r1.93 kern_mib.c --- sys/kern/kern_mib.c 28 Jan 2009 19:58:05 -0000 1.93 +++ sys/kern/kern_mib.c 4 Feb 2009 13:15:06 -0000 @@ -124,8 +124,8 @@ SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, "Version of POSIX attempting to comply to"); -SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, - 0, NGROUPS_MAX, "Maximum number of groups a user can belong to"); +SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RW, + 0, _NGROUPS_COMPAT, "Maximum number of groups allocated to a user"); SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, "Whether job control is available"); Index: sys/sys/param.h =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/sys/param.h,v retrieving revision 1.382 diff -b -u -r1.382 param.h --- sys/sys/param.h 28 Jan 2009 17:57:16 -0000 1.382 +++ sys/sys/param.h 4 Feb 2009 14:11:55 -0000 @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800062 /* Master, propagated to newvers */ +#define __FreeBSD_version 800060 /* Master, propagated to newvers */ #ifndef LOCORE #include <sys/types.h> @@ -77,7 +77,8 @@ #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_COMPAT + /* depreciated check sysctl/sysconf for NGROUPS_MAX value instead */ #define NOFILE OPEN_MAX /* max open files per process */ #define NOGROUP 65535 /* marker for empty group set member */ #define MAXHOSTNAMELEN 256 /* max hostname size */ Index: sys/sys/syslimits.h =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/sys/syslimits.h,v retrieving revision 1.23 diff -b -u -r1.23 syslimits.h --- sys/sys/syslimits.h 29 May 2007 15:14:46 -0000 1.23 +++ sys/sys/syslimits.h 3 Feb 2009 18:02:22 -0000 @@ -54,7 +54,6 @@ #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 OPEN_MAX #define OPEN_MAX 64 /* max open files per process */ #endif @@ -66,9 +65,35 @@ * We leave the following values undefined to force applications to either * assume conservative values or call sysconf() to get the current value. * - * HOST_NAME_MAX + * HOST_NAME_MAX NGROUPS_MAX * * (We should do this for most of the values currently defined here, * but many programs are not prepared to deal with this yet.) */ +/* + * here are some reference values in respect of the obsoleted + * NGROUPS_MAX value. + * nb: some apps appear to check NGROUPS_MAX as meaning that + * ... system has user groups (i.e. to #ifdef chunks of code). + * ... this is easy to change but maybe historically defined? + */ +#define _NGROUPS_RPC_MAX 16 /* reference only */ + /* nb: this is the old system max, so named + * ... because it's limit appears to + * ... have been derived from a limitation + * ... in RPC (and thereby NFS), where it's + * ... the max number of groups we can exchange */ +#define _NGROUPS_COMPAT _NGROUPS_RPC_MAX /* reference only */ + /* nb: although this is defined as equal to the rpc + * ... limit, i have defined it distintly so that + * ... we may distinguish (whilst updating) usage + * ... that is correctly explicit (i.e. should be 16) + * ... and usage that is only 16 because of an expected + * ... convention. hopefully we may remove these and + * ... define additional _NGROUPS_*_MAX for those defined + * ... uses. */ +#define _NGROUPS_SYS_MAX 65536 /* reference only */ + /* nb: the idea's to have this extensible + * ... indefinately, this is what linux have and + * ... should more than cover immediate needs */ #endif Index: usr.bin/catman/catman.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.bin/catman/catman.c,v retrieving revision 1.14 diff -b -u -r1.14 catman.c --- usr.bin/catman/catman.c 5 Dec 2005 14:22:12 -0000 1.14 +++ usr.bin/catman/catman.c 8 Feb 2009 22:51:44 -0000 @@ -93,8 +93,9 @@ enum Ziptype {NONE, BZIP, GZIP}; static uid_t uid; -static gid_t gids[NGROUPS_MAX]; +static gid_t *gids; static int ngids; +static int max_ngroups ; static int starting_dir; static char tmp_file[MAXPATHLEN]; struct stat test_st; @@ -789,7 +790,15 @@ /* NOTREACHED */ } } - ngids = getgroups(NGROUPS_MAX, gids); +/* allocate memory for group ids */ +#if _POSIX_VERSION > 199212 + max_ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_ngroups = NGROUPS_MAX ; +#else + max_ngroups = _NGROUPS_COMPAT ; +#endif + ngids = getgroups( max_ngroups, gids ) ; if ((starting_dir = open(".", 0)) < 0) { err(1, "."); } Index: usr.bin/newgrp/newgrp.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.bin/newgrp/newgrp.c,v retrieving revision 1.2 diff -b -u -r1.2 newgrp.c --- usr.bin/newgrp/newgrp.c 30 Oct 2003 15:14:34 -0000 1.2 +++ usr.bin/newgrp/newgrp.c 9 Feb 2009 22:05:53 -0000 @@ -146,9 +146,10 @@ static void addgroup(const char *grpname) { - gid_t grps[NGROUPS_MAX]; + gid_t *grps; long lgid; - int dbmember, i, ngrps; + int dbmember, i, ngrps, max_ngroups ; + /* XXX: should 'max_ngroups' be a static const variable? */ gid_t egid; struct group *grp; char *ep, *pass; @@ -185,9 +186,21 @@ } } - if ((ngrps = getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) { +#if _POSIX_VERSION >= 199212 + max_ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_ngroups = NGROUPS_MAX ; +#else + max_ngroups = _NGROUPS_COMPAT ; +#endif + grps = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ; + if( grps == NULL ) { + warn( "group set memory allocation" ) ; + return ; + } + if( (ngrps=getgroups(max_ngroups,(gid_t*)grps)) < 0 ) { warn("getgroups"); - return; + goto error_free ; } /* Remove requested gid from supp. list if it exists. */ @@ -201,7 +214,7 @@ if (setgroups(ngrps, (const gid_t *)grps) < 0) { PRIV_END; warn("setgroups"); - return; + goto error_free ; } PRIV_END; } @@ -210,14 +223,14 @@ if (setgid(grp->gr_gid)) { PRIV_END; warn("setgid"); - return; + goto error_free ; } PRIV_END; grps[0] = grp->gr_gid; /* 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 == max_ngroups ) warnx("too many groups"); else { grps[ngrps++] = egid; @@ -225,12 +238,15 @@ if (setgroups(ngrps, (const gid_t *)grps)) { PRIV_END; warn("setgroups"); - return; + goto error_free ; } PRIV_END; } } +error_free: + free( grps ) ; + return ; } static int Index: usr.sbin/chown/chown.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/chown/chown.c,v retrieving revision 1.29 diff -b -u -r1.29 chown.c --- usr.sbin/chown/chown.c 7 Aug 2004 04:19:37 -0000 1.29 +++ usr.sbin/chown/chown.c 8 Feb 2009 16:22:31 -0000 @@ -269,7 +269,8 @@ { static uid_t euid = -1; static int ngroups = -1; - gid_t groups[NGROUPS_MAX]; + static int max_groups ; + gid_t *groups; /* Check for chown without being root. */ if (errno != EPERM || (uid != (uid_t)-1 && @@ -279,16 +280,31 @@ } /* Check group membership; kernel just returns EPERM. */ +#if _POSIX_VERSION >= 199212 + max_groups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_groups = NGROUPS_MAX ; +#else + max_groups = _NGROUPS_COMPAT ; +#endif + groups = (gid_t*)calloc( max_groups, sizeof(gid_t) ) ; + if( groups == NULL ) { + warnx( "failed to allocate memory for group set" ) ; + goto exit_cleanup ; + } if (gid != (gid_t)-1 && ngroups == -1 && euid == (uid_t)-1 && (euid = geteuid()) != 0) { - ngroups = getgroups(NGROUPS_MAX, groups); + ngroups = getgroups( max_groups, groups ) ; while (--ngroups >= 0 && gid != groups[ngroups]); if (ngroups < 0) { warnx("you are not a member of group %s", gname); - return; + goto exit_cleanup ; } } warn("%s", file); +exit_cleanup: + free( groups ) ; + return ; } void Index: usr.sbin/chroot/chroot.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/chroot/chroot.c,v retrieving revision 1.11 diff -b -u -r1.11 chroot.c --- usr.sbin/chroot/chroot.c 7 Aug 2004 04:19:37 -0000 1.11 +++ usr.sbin/chroot/chroot.c 5 Feb 2009 23:29:48 -0000 @@ -59,6 +59,7 @@ char *user; /* user to switch to before running program */ char *group; /* group to switch to ... */ char *grouplist; /* group list to switch to ... */ +int max_ngroups; /* max number of groups allowable */ int main(argc, argv) @@ -69,12 +70,25 @@ 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; + int ch, gids ; +/* set some defaults */ gid = 0; uid = 0; + user = NULL ; + group = NULL ; + grouplist = NULL ; +#if _POSIX_VERSION >= 199212 + max_ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_ngroups = NGROUPS_MAX ; +#else + max_ngroups = _NGROUPS_COMPAT ; +#endif + +/* process command line options */ while ((ch = getopt(argc, argv, "G:g:u:")) != -1) { switch(ch) { case 'u': @@ -103,9 +117,12 @@ if (argc < 1) usage(); +/* if a group argument was passed then process it */ if (group != NULL) { + /* if the first char's a digit then assume it's a gid ... */ if (isdigit((unsigned char)*group)) { gid = (gid_t)strtoul(group, &endp, 0); + /* ... and back out that assumption if it proves wrong */ if (*endp != '\0') goto getgroup; } else { @@ -117,8 +134,15 @@ } } - for (gids = 0; - (p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX; ) { +/* process command line group list */ + if( grouplist != NULL ) { + gidlist = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ; + if( gidlist == NULL ) + errx( 1, "inadquate memory for group list" ) ; + for( gids = 0 ; + gids < max_ngroups && + (p=strsep(&grouplist,",")) != NULL ; ) + { if (*p == '\0') continue; @@ -135,9 +159,11 @@ } gids++; } - if (p != NULL && gids == NGROUPS_MAX) + if( p != NULL && gids == max_ngroups ) errx(1, "too many supplementary groups provided"); + } +/* set user from command line option, if supplied */ if (user != NULL) { if (isdigit((unsigned char)*user)) { uid = (uid_t)strtoul(user, &endp, 0); @@ -152,9 +178,11 @@ } } +/* change root */ if (chdir(argv[0]) == -1 || chroot(".") == -1) err(1, "%s", argv[0]); +/* set credentials */ if (gids && setgroups(gids, gidlist) == -1) err(1, "setgroups"); if (group && setgid(gid) == -1) @@ -162,11 +190,14 @@ if (user && setuid(uid) == -1) err(1, "setuid"); +/* exec the remaining arguments as the chroot'd command ... */ if (argv[1]) { execvp(argv[1], &argv[1]); err(1, "%s", argv[1]); + /* NOTREACHED */ } +/* ... or execute the default system shell */ if (!(shell = getenv("SHELL"))) shell = _PATH_BSHELL; execlp(shell, shell, "-i", (char *)NULL); Index: usr.sbin/gssd/gssd.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/gssd/gssd.c,v retrieving revision 1.1 diff -b -u -r1.1 gssd.c --- usr.sbin/gssd/gssd.c 3 Nov 2008 10:38:00 -0000 1.1 +++ usr.sbin/gssd/gssd.c 5 Feb 2009 16:16:37 -0000 @@ -464,8 +464,8 @@ result->uid = uid; getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw); if (pw) { - int len = NGRPS; - int groups[NGRPS]; + int len = AUTH_UNIX_NGROUPS ; + int groups[AUTH_UNIX_NGROUPS] ; result->gid = pw->pw_gid; getgrouplist(pw->pw_name, pw->pw_gid, groups, &len); Index: usr.sbin/mount_portalfs/cred.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/mount_portalfs/cred.c,v retrieving revision 1.1 diff -b -u -r1.1 cred.c --- usr.sbin/mount_portalfs/cred.c 11 Mar 2005 08:39:58 -0000 1.1 +++ usr.sbin/mount_portalfs/cred.c 16 Jan 2009 23:49:36 -0000 @@ -46,7 +46,7 @@ set_user_credentials(struct portal_cred *user, struct portal_cred *save) { save->pcr_uid = geteuid(); - if ((save->pcr_ngroups = getgroups(NGROUPS_MAX, save->pcr_groups)) < 0) + if( (save->pcr_ngroups=getgroups(_NGROUPS_COMPAT,save->pcr_groups)) < 0 ) return (-1); if (setgroups(user->pcr_ngroups, user->pcr_groups) < 0) return (-1); Index: usr.sbin/pppd/options.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/pppd/options.c,v retrieving revision 1.26 diff -b -u -r1.26 options.c --- usr.sbin/pppd/options.c 7 Nov 2007 10:53:38 -0000 1.26 +++ usr.sbin/pppd/options.c 10 Feb 2009 09:11:47 -0000 @@ -72,10 +72,6 @@ char *strdup(char *); #endif -#ifndef GIDSET_TYPE -#define GIDSET_TYPE gid_t -#endif - /* * Option variables and default values. */ @@ -779,23 +775,64 @@ int fd; { uid_t uid; - int ngroups, i; + int ngroups, max_ngroups, i; struct stat sbuf; - GIDSET_TYPE groups[NGROUPS_MAX]; + gid_t *groups; +/* get the uid */ uid = getuid(); +/* ... and return true if root */ +/* XXX: needs credential check */ if (uid == 0) return 1; + +/* if we're not root, get some info about the file */ if (fstat(fd, &sbuf) != 0) return 0; + +/* test for owner match with current process */ if (sbuf.st_uid == uid) return sbuf.st_mode & S_IRUSR; +/* ... and a group match */ if (sbuf.st_gid == getgid()) return sbuf.st_mode & S_IRGRP; - ngroups = getgroups(NGROUPS_MAX, groups); - for (i = 0; i < ngroups; ++i) - if (sbuf.st_gid == groups[i]) - return sbuf.st_mode & S_IRGRP; + +/* if we've still no luck then check the group list for permission match */ +#if _POSIX_VERSION >= 199212 + max_ngroups = sysconf( _SC_NGROUPS_MAX ) ; +#elif defined(NGROUPS_MAX) + max_ngroups = NGROUPS_MAX ; +#else + max_ngroups = _NGROUPS_COMPAT ; +#endif + groups = (gid_t*) calloc( max_ngroups, sizeof(gid_t) ) ; + if( groups == NULL ) { + /* if we cannot check groups correctly then assume 'fd' is unreadable + * XXX: this may be false as the converse is more likely. + * i.e. it would be failed readable on available groups + * and granted on full list, however, we just can't be + * psychic and i'm not about to code some idiotic loop that tries + * to get 'some' memory for partial testing. probably a better + * recourse would be to simply die here but that seems severe + * for a 'readable' test. + * NB: we don't need a 'full' allocation of memory to test the + * group list, only to store it. one idea would be to do this in + * 'blocks' + */ + option_error( 1, "unable to allocate memory for group list" ) ; + return( 0 ) ; + } +/* get groups */ + ngroups = getgroups( max_ngroups, groups ) ; +/* ... and test the group permission if matching */ + for( i = 0 ; i < ngroups ; ++i ) { + if (sbuf.st_gid == groups[i]) { + free( (void*)groups) ; + return( sbuf.st_mode & S_IRGRP ) ; + } + } +/* otherwise return other permissions match */ + free( (void*)groups ) ; return sbuf.st_mode & S_IROTH; } Index: usr.sbin/rpc.lockd/kern.c =================================================================== RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/rpc.lockd/kern.c,v retrieving revision 1.21 diff -b -u -r1.21 kern.c --- usr.sbin/rpc.lockd/kern.c 17 Aug 2006 05:55:20 -0000 1.21 +++ usr.sbin/rpc.lockd/kern.c 5 Feb 2009 16:22:17 -0000 @@ -239,15 +239,15 @@ int ngroups; ngroups = xucred->cr_ngroups - 1; - if (ngroups > NGRPS) - ngroups = NGRPS; - if (cl->cl_auth != NULL) - cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth); - cl->cl_auth = authunix_create(hostname, + if( ngroups > AUTH_UNIX_NGROUPS ) + ngroups = AUTH_UNIX_NGROUPS ; + if( cl->cl_auth != NULL ) + cl->cl_auth->ah_ops->ah_destroy( cl->cl_auth ) ; + cl->cl_auth = authunix_create( hostname, xucred->cr_uid, xucred->cr_groups[0], ngroups, - &xucred->cr_groups[1]); + &xucred->cr_groups[1] ) ; } --zYM0uCDKw75PZbzx--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090324110926.GA14099>