removal of NGROUPS_MAX dependancy from base

ttw+bsd at cobbled.net ttw+bsd at cobbled.net
Sat Feb 21 10:09:47 PST 2009


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.
-------------- next part --------------
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] ) ;
 }
 
 


More information about the freebsd-hackers mailing list