Skip site navigation (1)Skip section navigation (2)
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>