Subject: Re: HELP: su: setting user context: Invalid argument
To: Eric Fox <eric@fox.phoenix.az.us>
From: David Laight <david@l8s.co.uk>
List: netbsd-users
Date: 11/23/2002 16:39:18
> The fix (to make later groups be ignored) is:
> 
> Index: initgroups.c
> ===================================================================
> RCS file: /cvsroot/basesrc/lib/libc/gen/initgroups.c,v
> retrieving revision 1.19
> diff -u -r1.19 initgroups.c
> --- initgroups.c	2000/01/22 22:19:11	1.19
> +++ initgroups.c	2002/11/23 16:01:08
> @@ -64,7 +64,8 @@
>  	_DIAGASSERT(uname != NULL);
>  
>  	ngroups = NGROUPS;
> -	getgrouplist(uname, agroup, groups, &ngroups);
> +	if (getgrouplist(uname, agroup, groups, &ngroups) == -1)
> +		ngroups = NGROUPS;
>  	if (setgroups(ngroups, groups) < 0)
>  		return (-1);
>  	return (0);

The (slightly longer fix):

Index: initgroups.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/gen/initgroups.c,v
retrieving revision 1.19
diff -u -r1.19 initgroups.c
--- initgroups.c	2000/01/22 22:19:11	1.19
+++ initgroups.c	2002/11/23 16:31:47
@@ -48,6 +48,8 @@
 #include <assert.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
 
 #ifdef __weak_alias
 __weak_alias(initgroups,_initgroups)
@@ -58,14 +60,29 @@
 	const char *uname;
 	gid_t agroup;
 {
-	gid_t groups[NGROUPS];
+	gid_t groups_list[NGROUPS];
 	int ngroups;
+	gid_t *groups = groups_list;
+	int rval;
 
 	_DIAGASSERT(uname != NULL);
 
 	ngroups = NGROUPS;
-	getgrouplist(uname, agroup, groups, &ngroups);
-	if (setgroups(ngroups, groups) < 0)
-		return (-1);
-	return (0);
+	if (getgrouplist(uname, agroup, groups, &ngroups) == -1) {
+		int maxgroups = ngroups;
+		groups = calloc(maxgroups + 0u, sizeof *groups + 0u);
+		if (groups == NULL)
+			return -1;
+		if (getgrouplist(uname, agroup, groups, &ngroups) == -1)
+			ngroups = maxgroups;
+	}
+	rval = setgroups(ngroups, groups);
+	if (rval == -1 && errno == EINVAL) {
+		int ng = (int)sysconf(_SC_NGROUPS_MAX);
+		if (ng > 0 && ng < ngroups)
+			rval = setgroups(ng, groups);
+	}
+	if (groups != groups_list)
+		free(groups);
+	return rval;
 }

Will load all the groups the kernel will accept.
Indeed a larger on-stack array could be used to save parsing the
group file twice.

	David

-- 
David Laight: david@l8s.co.uk