]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: Make failure to get supplementary group list for a uid non-fatal
authorPeter Krempa <pkrempa@redhat.com>
Fri, 17 Jun 2016 13:32:58 +0000 (15:32 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 20 Jun 2016 15:35:55 +0000 (17:35 +0200)
Since introduction of the DAC security driver we've documented that
seclabels with a leading + can be used with numerical uid. This would
not work though with the rest of libvirt if the uid was not actually
used in the system as we'd fail when trying to get a list of
supplementary groups for the given uid. Since a uid without entry in
/etc/passwd (or other user database) will not have any supplementary
groups we can treat the failure to obtain them as such.

This patch modifies virGetGroupList to not report the error for missing
users and makes it return an empty list or just the group specified in
@gid.

All callers will grant less permissions to a user in case of failure of
this function and thus this change is safe.

src/util/virutil.c

index 392091b366470bc9aef690e9a2dc9965ea8f7c05..60da17b2f90df06e44d485263ab4cb85793c792d 100644 (file)
@@ -1120,29 +1120,30 @@ virGetGroupID(const char *group, gid_t *gid)
 
 /* 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. */
+ * storing a malloc'd result into @list. If uid is -1 or doesn't exist in the
+ * system database querying of the supplementary groups is skipped.
+ *
+ * Returns 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;
+    int ret = 0;
     char *user = NULL;
     gid_t primary;
 
     *list = NULL;
-    if (uid == (uid_t)-1)
-        return 0;
 
-    if (virGetUserEnt(uid, &user, &primary, NULL, NULL, false) < 0)
-        return -1;
-
-    ret = mgetgroups(user, primary, list);
-    if (ret < 0) {
-        sa_assert(!*list);
-        virReportSystemError(errno,
-                             _("cannot get group list for '%s'"), user);
-        goto cleanup;
+    /* invalid users have no supplementary groups */
+    if (uid != (uid_t)-1 &&
+        virGetUserEnt(uid, &user, &primary, NULL, NULL, true) >= 0) {
+        if ((ret = mgetgroups(user, primary, list)) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot get group list for '%s'"), user);
+            ret = -1;
+            goto cleanup;
+        }
     }
 
     if (gid != (gid_t)-1) {