]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: add virGetGroupList
authorEric Blake <eblake@redhat.com>
Tue, 21 May 2013 23:47:48 +0000 (17:47 -0600)
committerEric Blake <eblake@redhat.com>
Thu, 11 Jul 2013 21:25:53 +0000 (15:25 -0600)
Since neither getpwuid_r() nor initgroups() are safe to call in
between fork and exec (they obtain a mutex, but if some other
thread in the parent also held the mutex at the time of the fork,
the child will deadlock), we have to split out the functionality
that is unsafe.  At least glibc's initgroups() uses getgrouplist
under the hood, so the ideal split is to expose getgrouplist for
use before a fork.  Gnulib already gives us a nice wrapper via
mgetgroups; we wrap it once more to look up by uid instead of name.

* bootstrap.conf (gnulib_modules): Add mgetgroups.
* src/util/virutil.h (virGetGroupList): New declaration.
* src/util/virutil.c (virGetGroupList): New function.
* src/libvirt_private.syms (virutil.h): Export it.

Signed-off-by: Eric Blake <eblake@redhat.com>
bootstrap.conf
src/libvirt_private.syms
src/util/virutil.c
src/util/virutil.h

index 410e4f5dc46324219a836443a8a80f453ac4d000..1c59c22c358b395996dbbb3ed7dcba4531ebdc23 100644 (file)
@@ -71,6 +71,7 @@ listen
 localeconv
 maintainer-makefile
 manywarnings
+mgetgroups
 mkdtemp
 mkostemp
 mkostemps
index 59583ec7e2925ce2bf003a602c9016b5b6f54689..e56c7a9b29dc0daa4544913c12a6ccd105296310 100644 (file)
@@ -2002,6 +2002,7 @@ virGetDeviceID;
 virGetDeviceUnprivSGIO;
 virGetFCHostNameByWWN;
 virGetGroupID;
+virGetGroupList;
 virGetGroupName;
 virGetHostname;
 virGetUnprivSGIOSysfsPath;
index d7e61db37f1b6c4f45cbf778a00a41ffae296b86..136ff2565202604e1341447ab73c7193b9825228 100644 (file)
@@ -67,6 +67,7 @@
 #endif
 
 #include "c-ctype.h"
+#include "mgetgroups.h"
 #include "virerror.h"
 #include "virlog.h"
 #include "virbuffer.h"
@@ -970,6 +971,35 @@ virGetGroupID(const char *group, gid_t *gid)
     return 0;
 }
 
+
+/* Compute the list of supplementary groups associated with @uid, and
+ * including @gid in the list (unless it is -1), storing a malloc'd
+ * result into @list.  Return the size of the list on success, or -1
+ * on failure with error reported and errno set. May not be called
+ * between fork and exec. */
+int
+virGetGroupList(uid_t uid, gid_t gid, gid_t **list)
+{
+    int ret = -1;
+    char *user = NULL;
+
+    *list = NULL;
+    if (uid == (uid_t)-1)
+        return 0;
+
+    if (virGetUserEnt(uid, &user,
+                      gid == (gid_t)-1 ? &gid : NULL, NULL) < 0)
+        return -1;
+
+    ret = mgetgroups(user, gid, list);
+    if (ret < 0)
+        virReportSystemError(errno,
+                             _("cannot get group list for '%s'"), user);
+    VIR_FREE(user);
+    return ret;
+}
+
+
 /* Set the real and effective uid and gid to the given values, and call
  * initgroups so that the process has all the assumed group membership of
  * that uid. return 0 on success, -1 on failure (the original system error
index 280a18dc6ee0d1e497a0cfdf04322ba8a5a3f2ed..6480b073e8d88fba0d0858239e84419c6cfd141f 100644 (file)
@@ -115,6 +115,8 @@ char *virGetUserCacheDirectory(void);
 char *virGetUserRuntimeDirectory(void);
 char *virGetUserName(uid_t uid);
 char *virGetGroupName(gid_t gid);
+int virGetGroupList(uid_t uid, gid_t group, gid_t **groups)
+    ATTRIBUTE_NONNULL(3);
 int virGetUserID(const char *name,
                  uid_t *uid) ATTRIBUTE_RETURN_CHECK;
 int virGetGroupID(const char *name,