From 3e035a5d686888e5eba0b622dac459b65cdd99d3 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 4 Dec 2009 08:26:23 -0700 Subject: [PATCH] mgetgroups: add xgetgroups, and avoid ENOSYS failures ENOSYS implies that there are no supplemental groups, so we can treat it the same as a return of 0 from getgroups rather than exposing failure to the user. This in turn fixes a crash in coreutils' id, which freed an uninitialized pointer. * lib/mgetgroups.h (xgetgroups): New prototype. * lib/mgetgroups.c (xgetgroups): New wrapper. (mgetgroups): Handle ENOSYS. * modules/mgetgroups (Depends-on): Add realloc. Reported by Scott Harrison . Signed-off-by: Eric Blake --- ChangeLog | 7 +++++++ lib/mgetgroups.c | 31 +++++++++++++++++++++++++++---- lib/mgetgroups.h | 1 + modules/mgetgroups | 1 + 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15bdded15..48e102661 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-12-04 Eric Blake + mgetgroups: add xgetgroups, and avoid ENOSYS failures + * lib/mgetgroups.h (xgetgroups): New prototype. + * lib/mgetgroups.c (xgetgroups): New wrapper. + (mgetgroups): Handle ENOSYS. + * modules/mgetgroups (Depends-on): Add realloc. + Reported by Scott Harrison . + mgetgroups: avoid argument promotion issues with -1 * lib/mgetgroups.c (mgetgroups): A cast is required when checking for invalid gid_t. diff --git a/lib/mgetgroups.c b/lib/mgetgroups.c index 9a733d598..7a61db41d 100644 --- a/lib/mgetgroups.c +++ b/lib/mgetgroups.c @@ -116,13 +116,24 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) max_n_groups = (username ? getugroups (0, NULL, username, gid) - : getgroups (0, NULL) + (gid != (gid_t) -1)); + : getgroups (0, NULL)); - /* If we failed to count groups with NULL for a buffer, - try again with a non-NULL one, just in case. */ + /* If we failed to count groups because there is no supplemental + group support, then return an array containing just GID. + Otherwise, we fail for the same reason. */ if (max_n_groups < 0) - max_n_groups = 5; + { + if (errno == ENOSYS && (g = realloc_groupbuf (NULL, 1))) + { + *groups = g; + *g = gid; + return gid != (gid_t) -1; + } + return -1; + } + if (!username && gid != (gid_t) -1) + max_n_groups++; g = realloc_groupbuf (NULL, max_n_groups); if (g == NULL) return -1; @@ -133,6 +144,7 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) if (ng < 0) { + /* Failure is unexpected, but handle it anyway. */ int saved_errno = errno; free (g); errno = saved_errno; @@ -147,3 +159,14 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) *groups = g; return ng; } + +/* Like mgetgroups, but call xalloc_die on allocation failure. */ + +int +xgetgroups (char const *username, gid_t gid, gid_t **groups) +{ + int result = mgetgroups (username, gid, groups); + if (result == -1 && errno == ENOMEM) + xalloc_die (); + return result; +} diff --git a/lib/mgetgroups.h b/lib/mgetgroups.h index 909d84c64..4868d2881 100644 --- a/lib/mgetgroups.h +++ b/lib/mgetgroups.h @@ -17,3 +17,4 @@ #include int mgetgroups (const char *username, gid_t gid, gid_t **groups); +int xgetgroups (const char *username, gid_t gid, gid_t **groups); diff --git a/modules/mgetgroups b/modules/mgetgroups index 58ef74086..cd249dba3 100644 --- a/modules/mgetgroups +++ b/modules/mgetgroups @@ -9,6 +9,7 @@ m4/mgetgroups.m4 Depends-on: getgroups getugroups +realloc xalloc configure.ac: -- 2.11.0