virHashTablePtr binaries;
char *libDir;
char *runDir;
+ uid_t runUid;
+ gid_t runGid;
};
VIR_ONCE_GLOBAL_INIT(qemuCaps)
+struct _qemuCapsHookData {
+ uid_t runUid;
+ gid_t runGid;
+};
+typedef struct _qemuCapsHookData qemuCapsHookData;
+typedef qemuCapsHookData *qemuCapsHookDataPtr;
+
+static int qemuCapsHook(void * data)
+{
+ int ret;
+ qemuCapsHookDataPtr hookData = data;
+
+ if (!hookData) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("QEMU uid:gid not specified by caller"));
+ ret = -1;
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Switch QEMU uid:gid to %d:%d",
+ hookData->runUid, hookData->runGid);
+ ret = virSetUIDGID(hookData->runUid, hookData->runGid);
+
+cleanup:
+ return ret;
+}
+
static virCommandPtr
qemuCapsProbeCommand(const char *qemu,
- qemuCapsPtr caps)
+ qemuCapsPtr caps,
+ qemuCapsHookDataPtr hookData)
{
virCommandPtr cmd = virCommandNew(qemu);
virCommandAddEnvPassCommon(cmd);
virCommandClearCaps(cmd);
+ virCommandSetPreExecHook(cmd, qemuCapsHook, hookData);
return cmd;
}
}
static int
-qemuCapsProbeMachineTypes(qemuCapsPtr caps)
+qemuCapsProbeMachineTypes(qemuCapsPtr caps, qemuCapsHookDataPtr hookData)
{
char *output;
int ret = -1;
return -1;
}
- cmd = qemuCapsProbeCommand(caps->binary, caps);
+ cmd = qemuCapsProbeCommand(caps->binary, caps, hookData);
virCommandAddArgList(cmd, "-M", "?", NULL);
virCommandSetOutputBuffer(cmd, &output);
}
static int
-qemuCapsProbeCPUModels(qemuCapsPtr caps)
+qemuCapsProbeCPUModels(qemuCapsPtr caps, qemuCapsHookDataPtr hookData)
{
char *output = NULL;
int ret = -1;
return 0;
}
- cmd = qemuCapsProbeCommand(caps->binary, caps);
+ cmd = qemuCapsProbeCommand(caps->binary, caps, hookData);
virCommandAddArgList(cmd, "-cpu", "?", NULL);
virCommandSetOutputBuffer(cmd, &output);
static int
qemuCapsExtractDeviceStr(const char *qemu,
- qemuCapsPtr caps)
+ qemuCapsPtr caps,
+ qemuCapsHookDataPtr hookData)
{
char *output = NULL;
virCommandPtr cmd;
* understand '-device name,?', and always exits with status 1 for
* the simpler '-device ?', so this function is really only useful
* if -help includes "device driver,?". */
- cmd = qemuCapsProbeCommand(qemu, caps);
+ cmd = qemuCapsProbeCommand(qemu, caps, hookData);
virCommandAddArgList(cmd,
"-device", "?",
"-device", "pci-assign,?",
#define QEMU_SYSTEM_PREFIX "qemu-system-"
static int
-qemuCapsInitHelp(qemuCapsPtr caps)
+qemuCapsInitHelp(qemuCapsPtr caps, uid_t runUid, gid_t runGid)
{
virCommandPtr cmd = NULL;
unsigned int is_kvm;
int ret = -1;
const char *tmp;
struct utsname ut;
+ qemuCapsHookData hookData;
VIR_DEBUG("caps=%p", caps);
goto cleanup;
}
- cmd = qemuCapsProbeCommand(caps->binary, NULL);
+ hookData.runUid = runUid;
+ hookData.runGid = runGid;
+ cmd = qemuCapsProbeCommand(caps->binary, NULL, &hookData);
virCommandAddArgList(cmd, "-help", NULL);
virCommandSetOutputBuffer(cmd, &help);
* understands the 0.13.0+ notion of "-device driver,". */
if (qemuCapsGet(caps, QEMU_CAPS_DEVICE) &&
strstr(help, "-device driver,?") &&
- qemuCapsExtractDeviceStr(caps->binary, caps) < 0)
+ qemuCapsExtractDeviceStr(caps->binary, caps, &hookData) < 0)
goto cleanup;
- if (qemuCapsProbeCPUModels(caps) < 0)
+ if (qemuCapsProbeCPUModels(caps, &hookData) < 0)
goto cleanup;
- if (qemuCapsProbeMachineTypes(caps) < 0)
+ if (qemuCapsProbeMachineTypes(caps, &hookData) < 0)
goto cleanup;
ret = 0;
static int
qemuCapsInitQMP(qemuCapsPtr caps,
const char *libDir,
- const char *runDir)
+ const char *runDir,
+ uid_t runUid,
+ gid_t runGid)
{
int ret = -1;
virCommandPtr cmd = NULL;
char *monarg = NULL;
char *monpath = NULL;
char *pidfile = NULL;
+ qemuCapsHookData hookData;
/* the ".sock" sufix is important to avoid a possible clash with a qemu
* domain called "capabilities"
"-nographic",
"-M", "none",
"-qmp", monarg,
- "-pidfile", pidfile,
- "-daemonize",
NULL);
virCommandAddEnvPassCommon(cmd);
virCommandClearCaps(cmd);
+ hookData.runUid = runUid;
+ hookData.runGid = runGid;
+ virCommandSetPreExecHook(cmd, qemuCapsHook, &hookData);
+ virCommandSetPidFile(cmd, pidfile);
+ virCommandDaemonize(cmd);
if (virCommandRun(cmd, &status) < 0)
goto cleanup;
qemuCapsPtr qemuCapsNewForBinary(const char *binary,
const char *libDir,
- const char *runDir)
+ const char *runDir,
+ uid_t runUid,
+ gid_t runGid)
{
qemuCapsPtr caps = qemuCapsNew();
struct stat sb;
goto error;
}
- if ((rv = qemuCapsInitQMP(caps, libDir, runDir)) < 0)
+ if ((rv = qemuCapsInitQMP(caps, libDir, runDir, runUid, runGid)) < 0)
goto error;
if (!caps->usedQMP &&
- qemuCapsInitHelp(caps) < 0)
+ qemuCapsInitHelp(caps, runUid, runGid) < 0)
goto error;
return caps;
qemuCapsCachePtr
-qemuCapsCacheNew(const char *libDir, const char *runDir)
+qemuCapsCacheNew(const char *libDir, const char *runDir,
+ uid_t runUid, gid_t runGid)
{
qemuCapsCachePtr cache;
goto error;
}
+ cache->runUid = runUid;
+ cache->runGid = runGid;
+
return cache;
error:
if (!ret) {
VIR_DEBUG("Creating capabilities for %s",
binary);
- ret = qemuCapsNewForBinary(binary, cache->libDir, cache->runDir);
+ ret = qemuCapsNewForBinary(binary, cache->libDir, cache->runDir,
+ cache->runUid, cache->runGid);
if (ret) {
VIR_DEBUG("Caching capabilities %p for %s",
ret, binary);