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