mgetgroups: add xgetgroups, and avoid ENOSYS failures
authorEric Blake <ebb9@byu.net>
Fri, 4 Dec 2009 15:26:23 +0000 (08:26 -0700)
committerEric Blake <ebb9@byu.net>
Sat, 5 Dec 2009 01:02:53 +0000 (18:02 -0700)
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 <scott.gnu.2009@scottrix.co.uk>.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/mgetgroups.c
lib/mgetgroups.h
modules/mgetgroups

index 15bdded150c7c5534f4ed88a54eb6e531f450724..48e102661fc5e4fa3d2aef2120c341ad709385a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-12-04  Eric Blake  <ebb9@byu.net>
 
+       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 <scott.gnu.2009@scottrix.co.uk>.
+
        mgetgroups: avoid argument promotion issues with -1
        * lib/mgetgroups.c (mgetgroups): A cast is required when checking
        for invalid gid_t.
index 9a733d5984b01b8672de1cdc3970b753062df359..7a61db41d900661e3542ea650429a6b3c94405ab 100644 (file)
@@ -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;
+}
index 909d84c645aa29d6aaceaff45e277e0c722109af..4868d2881586b093026e45c43e1071303b22c1db 100644 (file)
@@ -17,3 +17,4 @@
 #include <sys/types.h>
 
 int mgetgroups (const char *username, gid_t gid, gid_t **groups);
+int xgetgroups (const char *username, gid_t gid, gid_t **groups);
index 58ef74086ab10427a29566820a744a71a35c8e41..cd249dba31421e97ab18e7cff23ca8c796ca39a8 100644 (file)
@@ -9,6 +9,7 @@ m4/mgetgroups.m4
 Depends-on:
 getgroups
 getugroups
+realloc
 xalloc
 
 configure.ac: