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 e8daeeb, 177db08, 397e6a7, and
74e0349) be retained by qemu when necessary. Apparently that
capability has been broken for non-root qemu every since it was
originally added.
---
src/util/vircommand.c | 76 ++++++---------------------------------------------
1 file changed, 8 insertions(+), 68 deletions(-)
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 2eb11f5..2419315 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -177,65 +177,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
@@ -637,18 +578,17 @@ virExec(virCommandPtr cmd)
}
- if (cmd->uid > 0 || cmd->gid > 0) {
- VIR_DEBUG("Setting child uid:gid to %u:%u", cmd->uid, cmd->gid);
- if (virSetUIDGID(cmd->uid, cmd->gid) < 0)
+ /* The steps above may need todo something privileged, so we delay
+ * setuid and clearing capabilities until the last minute.
+ */
+ if (cmd->uid > 0 || cmd->gid > 0 ||
+ cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
+ VIR_DEBUG("Setting child uid:gid to %u:%u with caps %llx",
+ cmd->uid, 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) {
--
1.8.1