virDomainFSDefPtr root;
virCommandPtr cmd = NULL;
int hasReboot;
+ gid_t *groups = NULL;
+ int ngroups;
if (NULL == vmDef) {
virReportError(VIR_ERR_INTERNAL_ERROR,
goto cleanup;
}
+ /* TODO is it safe to call it here or should this call be moved in
+ * front of the clone() as otherwise there might be a risk for a
+ * deadlock */
+ if ((ngroups = virGetGroupList(virCommandGetUID(cmd), virCommandGetGID(cmd),
+ &groups)) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
VIR_FREE(ttyPath);
if (ret == 0) {
VIR_DEBUG("Executing init binary");
/* this function will only return if an error occurred */
- ret = virCommandExec(cmd);
+ ret = virCommandExec(cmd, groups, ngroups);
}
if (ret != 0) {
virGetLastErrorMessage());
}
+ VIR_FREE(groups);
virCommandFree(cmd);
return ret;
}
}
static int
-virExecCommon(virCommandPtr cmd)
+virExecCommon(virCommandPtr cmd, gid_t *groups, int ngroups)
{
- 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",
ret = 0;
cleanup:
- VIR_FREE(groups);
return ret;
}
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]))) {
childerr = null;
}
+ if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, &groups)) < 0)
+ goto cleanup;
+
pid = virFork();
if (pid < 0)
}
# endif
- if (virExecCommon(cmd) < 0)
+ if (virExecCommon(cmd, groups, ngroups) < 0)
goto fork_error;
if (virCommandHandshakeChild(cmd) < 0)
should never jump here on error */
VIR_FREE(binarystr);
+ VIR_FREE(groups);
/* NB we don't virReportError() on any failures here
because the code which jumped here already raised
/**
* virCommandExec:
* @cmd: command to run
+ * @groups: array of supplementary group IDs used for the command
+ * @ngroups: number of group IDs in @groups
*
* Exec the command, replacing the current process. Meant to be called
* in the hook after already forking / cloning, so does not attempt to
* Will not return on success.
*/
#ifndef WIN32
-int virCommandExec(virCommandPtr cmd)
+int virCommandExec(virCommandPtr cmd, gid_t *groups, int ngroups)
{
if (!cmd ||cmd->has_error == ENOMEM) {
virReportOOMError();
return -1;
}
- if (virExecCommon(cmd) < 0)
+ if (virExecCommon(cmd, groups, ngroups) < 0)
return -1;
execve(cmd->args[0], cmd->args, cmd->env);
return -1;
}
#else
-int virCommandExec(virCommandPtr cmd ATTRIBUTE_UNUSED)
+int virCommandExec(virCommandPtr cmd ATTRIBUTE_UNUSED, gid_t *groups ATTRIBUTE_UNUSED,
+ int ngroups ATTRIBUTE_UNUSED)
{
/* Mingw execve() has a broken signature. Disable this
* function until gnulib fixes the signature, since we
int rv = 0;
ssize_t tries = 100;
pid_t pid;
+ gid_t *groups = NULL;
+ int ngroups;
+ virCommandPtr cmd = virCommandNew("some/nonexistent/binary");
if (pipe(pipeFD) < 0) {
fprintf(stderr, "Unable to create pipe\n");
goto cleanup;
}
+ if ((ngroups = virGetGroupList(virCommandGetUID(cmd), virCommandGetGID(cmd),
+ &groups)) < 0)
+ goto cleanup;
+
/* Now, fork and try to exec a nonexistent binary. */
pid = virFork();
if (pid < 0) {
if (pid == 0) {
/* Child */
- virCommandPtr cmd = virCommandNew("some/nonexistent/binary");
-
- rv = virCommandExec(cmd);
-
- virCommandFree(cmd);
+ rv = virCommandExec(cmd, groups, ngroups);
if (safewrite(pipeFD[1], &rv, sizeof(rv)) < 0)
fprintf(stderr, "Unable to write to pipe\n");
cleanup:
VIR_FORCE_CLOSE(pipeFD[0]);
VIR_FORCE_CLOSE(pipeFD[1]);
+ VIR_FREE(groups);
+ virCommandFree(cmd);
return ret;
}