From owner-freebsd-hackers@FreeBSD.ORG Sat Feb 21 18:09:46 2009 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B8EED106564A for ; Sat, 21 Feb 2009 18:09:46 +0000 (UTC) (envelope-from fergus@cobbled.net) Received: from mail1.slb.deg.dub.stisp.net (mail1.slb.deg.dub.stisp.net [84.203.253.98]) by mx1.freebsd.org (Postfix) with SMTP id C298F8FC18 for ; Sat, 21 Feb 2009 18:09:45 +0000 (UTC) (envelope-from fergus@cobbled.net) Received: (qmail 5442 invoked from network); 21 Feb 2009 18:09:43 -0000 Received: from unknown (HELO holyman.cobbled.net) (84.203.180.117) by mail1.slb.deg.dub.stisp.net with SMTP; 21 Feb 2009 18:09:43 -0000 Received: by holyman.cobbled.net (Postfix, from userid 16385) id F31331031D; Sat, 21 Feb 2009 18:09:42 +0000 (UTC) Date: Fri, 13 Feb 2009 11:54:26 +0000 From: ttw+bsd@cobbled.net To: hackers@freebsd.org Message-ID: <20090213115426.GA15211@holyman.cobbled.net> Mail-Followup-To: hackers@freebsd.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="jRHKVT23PllUwdXP" Content-Disposition: inline Resent-From: ttw@cobbled.net Resent-Date: Sat, 21 Feb 2009 18:09:42 +0000 Resent-To: hackers@freebsd.org Resent-Message-Id: <20090221180942.F31331031D@holyman.cobbled.net> Cc: Subject: removal of NGROUPS_MAX dependancy from base X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 21 Feb 2009 18:09:47 -0000 --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: inline attached is the first in a series of patches that is intended to remove the current limitation on group membership. this patch should remove the dependancy on the definition of NGROUPS_MAX as a static constant and implement it as a writable sysconf variable of the same. it should also make the necessary changes to the codebase to support those. i need some guidance as to what i should re-define NGROUPS_MAX to be (so that code that depends on it can continue to operate, i'm thinking just make it 16 but perhaps it would be worth extending the default while we're at it to something like 64??). i also need feedback on any braindamage in the current changes. the next step will be to extend the kernel groups and map them back to the user structs / calls. finally i'll extend the user groups and implement those calls. nb: not tested the code (it builds) ... was intending to test it on my XEN box but only just realised that Xen on amd64 isn't working. :-( happy for any questions that may help guide the process. --jRHKVT23PllUwdXP 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 @@ -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] ) ; } --jRHKVT23PllUwdXP--