]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: maintain caps when running command with uid != 0
authorLaine Stump <laine@laine.org>
Thu, 7 Feb 2013 16:45:27 +0000 (11:45 -0500)
committerLaine Stump <laine@laine.org>
Wed, 13 Feb 2013 21:11:16 +0000 (16:11 -0500)
virCommand was previously calling virSetUIDGID() to change the uid and
gid of the child process, then separately calling
virSetCapabilities(). This did not work if the desired uid was != 0,
since a setuid to anything other than 0 normally clears all
capabilities bits.

The solution is to use the new virSetUIDGIDWithCaps(), sending it the
uid, gid, and capabilities bits. This will get the new process setup
properly.

Since the static functions virSetCapabilities() and
virClearCapabilities are no longer called, they have been removed.

NOTE: When combined with "filecap $path-to-qemu sys_rawio", this patch
will make CAP_SYS_RAWIO (which is required for passthrough of generic
scsi commands to a guest - see commits e8daeeb177db08397e6a7, and
74e0349) be retained by qemu when necessary. Apparently that
capability has been broken for non-root qemu ever since it was
originally added.

src/util/vircommand.c

index b0361dc82d73bebf4f0f52171c89c77cf7057b3a..5837feec79d3c3c3e100ce45f4c5484fbef8c83f 100644 (file)
@@ -182,65 +182,6 @@ virCommandFDSet(int fd,
 
 #ifndef WIN32
 
-static int virClearCapabilities(void) ATTRIBUTE_UNUSED;
-
-# if WITH_CAPNG
-static int virClearCapabilities(void)
-{
-    int ret;
-
-    capng_clear(CAPNG_SELECT_BOTH);
-
-    if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot clear process capabilities %d"), ret);
-        return -1;
-    }
-
-    return 0;
-}
-
-/**
- * virSetCapabilities:
- *  @capabilities - capability flag to set.
- *                  In case of 0, this function is identical to
- *                  virClearCapabilities()
- *
- */
-static int virSetCapabilities(unsigned long long capabilities)
-{
-    int ret, i;
-
-    capng_clear(CAPNG_SELECT_BOTH);
-
-    for (i = 0; i <= CAP_LAST_CAP; i++) {
-        if (capabilities & (1ULL << i))
-            capng_update(CAPNG_ADD, CAPNG_BOUNDING_SET, i);
-    }
-
-    if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot apply process capabilities %d"), ret);
-        return -1;
-    }
-
-    return 0;
-}
-# else
-static int virClearCapabilities(void)
-{
-//    VIR_WARN("libcap-ng support not compiled in, unable to clear "
-//             "capabilities");
-    return 0;
-}
-
-static int
-virSetCapabilities(unsigned long long capabilities ATTRIBUTE_UNUSED)
-{
-    return 0;
-}
-# endif
-
 /**
  * virFork:
  * @pid - a pointer to a pid_t that will receive the return value from
@@ -645,19 +586,17 @@ virExec(virCommandPtr cmd)
     }
 # endif
 
-    if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1) {
-        VIR_DEBUG("Setting child uid:gid to %d:%d",
-                  (int)cmd->uid, (int)cmd->gid);
-        if (virSetUIDGID(cmd->uid, cmd->gid) < 0)
+    /* The steps above may need to do something privileged, so we delay
+     * setuid and clearing capabilities until the last minute.
+     */
+    if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
+        cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
+        VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
+                  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
+        if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, cmd->capabilities) < 0)
             goto fork_error;
     }
 
-    /* The steps above may need todo something privileged, so
-     * we delay clearing capabilities until the last minute */
-    if (cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS))
-        if (virSetCapabilities(cmd->capabilities) < 0)
-            goto fork_error;
-
     if (cmd->pwd) {
         VIR_DEBUG("Running child in %s", cmd->pwd);
         if (chdir(cmd->pwd) < 0) {