]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
virGetGroupList: always include the primary group
authorGuido Günther <agx@sigxcpu.org>
Mon, 5 Aug 2013 09:07:27 +0000 (11:07 +0200)
committerGuido Günther <agx@sigxcpu.org>
Tue, 6 Aug 2013 20:52:40 +0000 (22:52 +0200)
The change from initgroups to virGetGroupList/setgroups in
cab36cfe71ba83b71e536ba5c98e596f02b697b0 dropped the primary group from
processes group list iff the passed in group to virGetGroupList differs
from the user's primary group.

So always include the primary group to bring back the old behaviour.

Debian has the kvm group as primary group but uses
libvirt-qemu:libvirt-qemu as user:group to run the kvm process so
without this change the /dev/kvm is inaccessible.

src/util/virutil.c

index 3abcd53a47b68ff4938207872b4f31a42a17165e..3de72ea1af670cf299c3acaf4c9a5bab6ee340ef 100644 (file)
@@ -983,29 +983,49 @@ virGetGroupID(const char *group, gid_t *gid)
 }
 
 
-/* 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. */
+/* Compute the list of primary and 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;
+    gid_t primary;
 
     *list = NULL;
     if (uid == (uid_t)-1)
         return 0;
 
-    if (virGetUserEnt(uid, &user,
-                      gid == (gid_t)-1 ? &gid : NULL, NULL) < 0)
+    if (virGetUserEnt(uid, &user, &primary, NULL) < 0)
         return -1;
 
-    ret = mgetgroups(user, gid, list);
-    if (ret < 0)
+    ret = mgetgroups(user, primary, list);
+    if (ret < 0) {
         virReportSystemError(errno,
                              _("cannot get group list for '%s'"), user);
+        goto cleanup;
+    }
+
+    if (gid != (gid_t)-1) {
+        size_t n = ret;
+
+        for (size_t i = 0; i < ret; i++) {
+            if ((*list)[i] == gid)
+                goto cleanup;
+        }
+        if (VIR_APPEND_ELEMENT(*list, n, gid) < 0) {
+            ret = -1;
+            VIR_FREE(*list);
+            goto cleanup;
+        } else {
+            ret = n;
+        }
+    }
+
+cleanup:
     VIR_FREE(user);
     return ret;
 }