diff --git a/src/util/vircommand.c b/src/util/vircommand.c index f672101f22..ac56a638a8 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -639,8 +639,10 @@ virExec(virCommandPtr cmd) 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) + if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, cmd->capabilities, + !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0) { goto fork_error; + } } if (cmd->pwd) { diff --git a/src/util/virutil.c b/src/util/virutil.c index 4605c78ca7..a0d15302dc 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -2998,18 +2998,21 @@ virGetGroupName(gid_t gid ATTRIBUTE_UNUSED) * errno). */ int -virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits) +virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits, + bool clearExistingCaps) { int ii, capng_ret, ret = -1; bool need_setgid = false, need_setuid = false; bool need_prctl = false, need_setpcap = false; - /* First drop all caps except those in capBits + the extra ones we - * need to change uid/gid and change the capabilities bounding - * set. + /* First drop all caps (unless the requested uid is "unchanged" or + * root and clearExistingCaps wasn't requested), then add back + * those in capBits + the extra ones we need to change uid/gid and + * change the capabilities bounding set. */ - capng_clear(CAPNG_SELECT_BOTH); + if (clearExistingCaps || (uid != -1 && uid != 0)) + capng_clear(CAPNG_SELECT_BOTH); for (ii = 0; ii <= CAP_LAST_CAP; ii++) { if (capBits & (1ULL << ii)) { @@ -3095,7 +3098,8 @@ cleanup: int virSetUIDGIDWithCaps(uid_t uid, gid_t gid, - unsigned long long capBits ATTRIBUTE_UNUSED) + unsigned long long capBits ATTRIBUTE_UNUSED, + bool clearExistingCaps ATTRIBUTE_UNUSED) { return virSetUIDGID(uid, gid); } diff --git a/src/util/virutil.h b/src/util/virutil.h index 2dc3403821..665ad78edd 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -54,7 +54,8 @@ int virPipeReadUntilEOF(int outfd, int errfd, char **outbuf, char **errbuf); int virSetUIDGID(uid_t uid, gid_t gid); -int virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits); +int virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits, + bool clearExistingCaps); int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;