idvec_merge_implied_gids (a part of libshouldbeinlibc) only merges in
primary ids and not secondary ids as it should. This patch corrects
that. The following is a test program showing what happened before and
after:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <idvec.h>
int
main (int argc, char *argv[])
{
int i;
char **arg;
struct idvec *uids = make_idvec ();
struct idvec *gids = make_idvec ();
for (arg = &argv[1]; *arg; arg ++)
idvec_add (uids, atoi (*arg));
idvec_merge_implied_gids (gids, uids);
for (i = 0; i < gids->num; i ++)
printf ("%d ", gids->ids[i]);
printf ("\n");
return 0;
}
$ grep neal /etc/group
adm:1bTB8THYRhlbo:4:neal
neal:x:1000:
$ ./idvec-test 1000
1000
$ ./idvec-test-new 1000
1000 4
I am also worried about the code to cache the groups associated with an
id: if the program is long running and things change, the cache will
become stale; this should be removed.
diff --exclude CVS -Nur hurd-20010307-snapshot/libshouldbeinlibc/ChangeLog
hurd-20010313/libshouldbeinlibc/ChangeLog
--- hurd-20010307-snapshot/libshouldbeinlibc/ChangeLog Sun Feb 25 23:18:19 2001
+++ hurd-20010313/libshouldbeinlibc/ChangeLog Sat Mar 17 08:44:57 2001
@@ -1,3 +1,9 @@
+2001-03-17 Neal H Walfield <[EMAIL PROTECTED]>
+
+ * idvec-impgids.c (idvec_merge_implied_gids): Add code to
+ check for secondary groups.
+ (_merge): Free cache on failure.
+
2001-02-25 Roland McGrath <[EMAIL PROTECTED]>
* idvec.h: Include <string.h> for memcmp decl.
diff --exclude CVS -Nur hurd-20010307-snapshot/libshouldbeinlibc/idvec-impgids.c
hurd-20010313/libshouldbeinlibc/idvec-impgids.c
--- hurd-20010307-snapshot/libshouldbeinlibc/idvec-impgids.c Wed Aug 6 22:57:46
1997
+++ hurd-20010313/libshouldbeinlibc/idvec-impgids.c Sat Mar 17 08:19:00 2001
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <errno.h>
+#include <alloca.h>
#include <idvec.h>
#include <pwd.h>
#include <grp.h>
@@ -84,7 +85,11 @@
if (! cache)
err = ENOMEM;
else
- err = idvec_add_new (cache, pw->pw_gid);
+ {
+ err = idvec_add_new (cache, pw->pw_gid);
+ if (err)
+ idvec_free (cache);
+ }
#endif
if (! err)
@@ -112,12 +117,49 @@
idvec_merge_implied_gids (struct idvec *gids, const struct idvec *uids)
{
int i;
- error_t err = 0;
+ error_t initial_err = 0;
+#define ERR(err) \
+ do { if ((err) && ! initial_err) initial_err = err; } while (0)
+
+ if (uids->num == 0)
+ return 0;
+
+ /* Merge the primary group associated with each uid. */
for (i = 0; i < uids->num; i++)
- {
- error_t this_err = _merge_implied_gids (gids, uids->ids[i]);
- if (this_err && !err)
- err = this_err;
- }
- return err;
+ ERR (_merge_implied_gids (gids, uids->ids[i]));
+
+ /* Merge the secondary group associated with each uid. */
+ {
+ struct group *group;
+ char *names[uids->num];
+ int last_name = 0;
+
+ setgrent ();
+
+ /* getgrent returns a string and we are only given the numerical uids.
+ Build a list of strings from the uids. */
+ for (i = 0; i < uids->num; i ++)
+ {
+ struct passwd *passwd = getpwuid (uids->ids[i]);
+ if (passwd)
+ names[last_name ++] = strdupa (passwd->pw_name);
+ }
+
+ if (last_name == 0)
+ goto out;
+
+ while ((group = getgrent ()))
+ {
+ char **member;
+ for (i = 0; i < last_name; i ++)
+ for (member = group->gr_mem; *member; member ++)
+ if (strcmp (*member, names[i]) == 0)
+ ERR (idvec_add (gids, group->gr_gid));
+ }
+
+ endgrent ();
+ }
+
+out:
+ return initial_err;
}
PGP signature