virCommand is a version of virExec that doesn't fork, however it is
just calling execve and doesn't honors setting uid/gid and pwd.
This commit extrac those pieces from virExec() to a virExecCommon()
function that is called from both virExec() and virCommandExec().
---
src/util/vircommand.c | 69 +++++++++++++++++++++++++++++----------------------
1 file changed, 40 insertions(+), 29 deletions(-)
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e1bbc0526..60c1121da 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -464,6 +464,41 @@ virCommandHandshakeChild(virCommandPtr cmd)
return 0;
}
+static int
+virExecCommon(virCommandPtr cmd)
+{
+ gid_t *groups = NULL;
+ int ngroups;
+ int ret = -1;
+
+ if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, &groups)) < 0)
+ goto cleanup;
+
+ 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, groups, ngroups,
+ cmd->capabilities,
+ !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0)
+ goto cleanup;
+ }
+
+ if (cmd->pwd) {
+ VIR_DEBUG("Running child in %s", cmd->pwd);
+ if (chdir(cmd->pwd) < 0) {
+ virReportSystemError(errno,
+ _("Unable to change to %s"), cmd->pwd);
+ goto cleanup;
+ }
+ }
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(groups);
+ return ret;
+}
+
/*
* virExec:
* @cmd virCommandPtr containing all information about the program to
@@ -484,8 +519,6 @@ virExec(virCommandPtr cmd)
const char *binary = NULL;
int ret;
struct sigaction waxon, waxoff;
- gid_t *groups = NULL;
- int ngroups;
if (cmd->args[0][0] != '/') {
if (!(binary = binarystr = virFindFileInPath(cmd->args[0]))) {
@@ -556,9 +589,6 @@ virExec(virCommandPtr cmd)
childerr = null;
}
- if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, &groups)) < 0)
- goto cleanup;
-
pid = virFork();
if (pid < 0)
@@ -578,7 +608,6 @@ virExec(virCommandPtr cmd)
cmd->pid = pid;
VIR_FREE(binarystr);
- VIR_FREE(groups);
return 0;
}
@@ -727,28 +756,8 @@ virExec(virCommandPtr cmd)
}
# endif
- /* 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, groups, ngroups,
- cmd->capabilities,
- !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0) {
- goto fork_error;
- }
- }
-
- if (cmd->pwd) {
- VIR_DEBUG("Running child in %s", cmd->pwd);
- if (chdir(cmd->pwd) < 0) {
- virReportSystemError(errno,
- _("Unable to change to %s"), cmd->pwd);
- goto fork_error;
- }
- }
+ if (virExecCommon(cmd) < 0)
+ goto fork_error;
if (virCommandHandshakeChild(cmd) < 0)
goto fork_error;
@@ -789,7 +798,6 @@ virExec(virCommandPtr cmd)
/* This is cleanup of parent process only - child
should never jump here on error */
- VIR_FREE(groups);
VIR_FREE(binarystr);
/* NB we don't virReportError() on any failures here
@@ -2166,6 +2174,9 @@ int virCommandExec(virCommandPtr cmd)
return -1;
}
+ if (virExecCommon(cmd) < 0)
+ return -1;
+
execve(cmd->args[0], cmd->args, cmd->env);
virReportSystemError(errno,
--
2.12.2