提交 1a50ba2c 编写于 作者: V Viktor Mihajlovski 提交者: Daniel P. Berrange

qemu: Fix QMP Capabability Probing Failure

QMP Capability probing will fail if QEMU cannot bind to the
QMP monitor socket in the qemu_driver->libDir directory.
That's because the child process is stripped of all
capabilities and this directory is chown'ed to the configured
QEMU user/group (normally qemu:qemu) by the QEMU driver.

To prevent this from happening, the driver startup will now pass
the QEMU uid and gid down to the capability probing code.
All capability probing invocations of QEMU will be run with
the configured QEMU uid instead of libvirtd's.

Furter, the pid file handling is moved to libvirt, as QEMU
cannot write to the qemu_driver->runDir (root:root). This also
means that the libvirt daemonizing must be used.
Signed-off-by: NViktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
上级 7a95eccc
...@@ -223,6 +223,8 @@ struct _qemuCapsCache { ...@@ -223,6 +223,8 @@ struct _qemuCapsCache {
virHashTablePtr binaries; virHashTablePtr binaries;
char *libDir; char *libDir;
char *runDir; char *runDir;
uid_t runUid;
gid_t runGid;
}; };
...@@ -241,9 +243,37 @@ static int qemuCapsOnceInit(void) ...@@ -241,9 +243,37 @@ static int qemuCapsOnceInit(void)
VIR_ONCE_GLOBAL_INIT(qemuCaps) 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 static virCommandPtr
qemuCapsProbeCommand(const char *qemu, qemuCapsProbeCommand(const char *qemu,
qemuCapsPtr caps) qemuCapsPtr caps,
qemuCapsHookDataPtr hookData)
{ {
virCommandPtr cmd = virCommandNew(qemu); virCommandPtr cmd = virCommandNew(qemu);
...@@ -256,6 +286,7 @@ qemuCapsProbeCommand(const char *qemu, ...@@ -256,6 +286,7 @@ qemuCapsProbeCommand(const char *qemu,
virCommandAddEnvPassCommon(cmd); virCommandAddEnvPassCommon(cmd);
virCommandClearCaps(cmd); virCommandClearCaps(cmd);
virCommandSetPreExecHook(cmd, qemuCapsHook, hookData);
return cmd; return cmd;
} }
...@@ -342,7 +373,7 @@ no_memory: ...@@ -342,7 +373,7 @@ no_memory:
} }
static int static int
qemuCapsProbeMachineTypes(qemuCapsPtr caps) qemuCapsProbeMachineTypes(qemuCapsPtr caps, qemuCapsHookDataPtr hookData)
{ {
char *output; char *output;
int ret = -1; int ret = -1;
...@@ -359,7 +390,7 @@ qemuCapsProbeMachineTypes(qemuCapsPtr caps) ...@@ -359,7 +390,7 @@ qemuCapsProbeMachineTypes(qemuCapsPtr caps)
return -1; return -1;
} }
cmd = qemuCapsProbeCommand(caps->binary, caps); cmd = qemuCapsProbeCommand(caps->binary, caps, hookData);
virCommandAddArgList(cmd, "-M", "?", NULL); virCommandAddArgList(cmd, "-M", "?", NULL);
virCommandSetOutputBuffer(cmd, &output); virCommandSetOutputBuffer(cmd, &output);
...@@ -498,7 +529,7 @@ cleanup: ...@@ -498,7 +529,7 @@ cleanup:
} }
static int static int
qemuCapsProbeCPUModels(qemuCapsPtr caps) qemuCapsProbeCPUModels(qemuCapsPtr caps, qemuCapsHookDataPtr hookData)
{ {
char *output = NULL; char *output = NULL;
int ret = -1; int ret = -1;
...@@ -516,7 +547,7 @@ qemuCapsProbeCPUModels(qemuCapsPtr caps) ...@@ -516,7 +547,7 @@ qemuCapsProbeCPUModels(qemuCapsPtr caps)
return 0; return 0;
} }
cmd = qemuCapsProbeCommand(caps->binary, caps); cmd = qemuCapsProbeCommand(caps->binary, caps, hookData);
virCommandAddArgList(cmd, "-cpu", "?", NULL); virCommandAddArgList(cmd, "-cpu", "?", NULL);
virCommandSetOutputBuffer(cmd, &output); virCommandSetOutputBuffer(cmd, &output);
...@@ -1530,7 +1561,8 @@ qemuCapsParseDeviceStr(qemuCapsPtr caps, const char *str) ...@@ -1530,7 +1561,8 @@ qemuCapsParseDeviceStr(qemuCapsPtr caps, const char *str)
static int static int
qemuCapsExtractDeviceStr(const char *qemu, qemuCapsExtractDeviceStr(const char *qemu,
qemuCapsPtr caps) qemuCapsPtr caps,
qemuCapsHookDataPtr hookData)
{ {
char *output = NULL; char *output = NULL;
virCommandPtr cmd; virCommandPtr cmd;
...@@ -1544,7 +1576,7 @@ qemuCapsExtractDeviceStr(const char *qemu, ...@@ -1544,7 +1576,7 @@ qemuCapsExtractDeviceStr(const char *qemu,
* understand '-device name,?', and always exits with status 1 for * understand '-device name,?', and always exits with status 1 for
* the simpler '-device ?', so this function is really only useful * the simpler '-device ?', so this function is really only useful
* if -help includes "device driver,?". */ * if -help includes "device driver,?". */
cmd = qemuCapsProbeCommand(qemu, caps); cmd = qemuCapsProbeCommand(qemu, caps, hookData);
virCommandAddArgList(cmd, virCommandAddArgList(cmd,
"-device", "?", "-device", "?",
"-device", "pci-assign,?", "-device", "pci-assign,?",
...@@ -2094,7 +2126,7 @@ int qemuCapsProbeQMP(qemuCapsPtr caps, ...@@ -2094,7 +2126,7 @@ int qemuCapsProbeQMP(qemuCapsPtr caps,
#define QEMU_SYSTEM_PREFIX "qemu-system-" #define QEMU_SYSTEM_PREFIX "qemu-system-"
static int static int
qemuCapsInitHelp(qemuCapsPtr caps) qemuCapsInitHelp(qemuCapsPtr caps, uid_t runUid, gid_t runGid)
{ {
virCommandPtr cmd = NULL; virCommandPtr cmd = NULL;
unsigned int is_kvm; unsigned int is_kvm;
...@@ -2102,6 +2134,7 @@ qemuCapsInitHelp(qemuCapsPtr caps) ...@@ -2102,6 +2134,7 @@ qemuCapsInitHelp(qemuCapsPtr caps)
int ret = -1; int ret = -1;
const char *tmp; const char *tmp;
struct utsname ut; struct utsname ut;
qemuCapsHookData hookData;
VIR_DEBUG("caps=%p", caps); VIR_DEBUG("caps=%p", caps);
...@@ -2123,7 +2156,9 @@ qemuCapsInitHelp(qemuCapsPtr caps) ...@@ -2123,7 +2156,9 @@ qemuCapsInitHelp(qemuCapsPtr caps)
goto cleanup; goto cleanup;
} }
cmd = qemuCapsProbeCommand(caps->binary, NULL); hookData.runUid = runUid;
hookData.runGid = runGid;
cmd = qemuCapsProbeCommand(caps->binary, NULL, &hookData);
virCommandAddArgList(cmd, "-help", NULL); virCommandAddArgList(cmd, "-help", NULL);
virCommandSetOutputBuffer(cmd, &help); virCommandSetOutputBuffer(cmd, &help);
...@@ -2153,13 +2188,13 @@ qemuCapsInitHelp(qemuCapsPtr caps) ...@@ -2153,13 +2188,13 @@ qemuCapsInitHelp(qemuCapsPtr caps)
* understands the 0.13.0+ notion of "-device driver,". */ * understands the 0.13.0+ notion of "-device driver,". */
if (qemuCapsGet(caps, QEMU_CAPS_DEVICE) && if (qemuCapsGet(caps, QEMU_CAPS_DEVICE) &&
strstr(help, "-device driver,?") && strstr(help, "-device driver,?") &&
qemuCapsExtractDeviceStr(caps->binary, caps) < 0) qemuCapsExtractDeviceStr(caps->binary, caps, &hookData) < 0)
goto cleanup; goto cleanup;
if (qemuCapsProbeCPUModels(caps) < 0) if (qemuCapsProbeCPUModels(caps, &hookData) < 0)
goto cleanup; goto cleanup;
if (qemuCapsProbeMachineTypes(caps) < 0) if (qemuCapsProbeMachineTypes(caps, &hookData) < 0)
goto cleanup; goto cleanup;
ret = 0; ret = 0;
...@@ -2242,7 +2277,9 @@ qemuCapsInitQMPBasic(qemuCapsPtr caps) ...@@ -2242,7 +2277,9 @@ qemuCapsInitQMPBasic(qemuCapsPtr caps)
static int static int
qemuCapsInitQMP(qemuCapsPtr caps, qemuCapsInitQMP(qemuCapsPtr caps,
const char *libDir, const char *libDir,
const char *runDir) const char *runDir,
uid_t runUid,
gid_t runGid)
{ {
int ret = -1; int ret = -1;
virCommandPtr cmd = NULL; virCommandPtr cmd = NULL;
...@@ -2254,6 +2291,7 @@ qemuCapsInitQMP(qemuCapsPtr caps, ...@@ -2254,6 +2291,7 @@ qemuCapsInitQMP(qemuCapsPtr caps,
char *monarg = NULL; char *monarg = NULL;
char *monpath = NULL; char *monpath = NULL;
char *pidfile = NULL; char *pidfile = NULL;
qemuCapsHookData hookData;
/* the ".sock" sufix is important to avoid a possible clash with a qemu /* the ".sock" sufix is important to avoid a possible clash with a qemu
* domain called "capabilities" * domain called "capabilities"
...@@ -2289,11 +2327,14 @@ qemuCapsInitQMP(qemuCapsPtr caps, ...@@ -2289,11 +2327,14 @@ qemuCapsInitQMP(qemuCapsPtr caps,
"-nographic", "-nographic",
"-M", "none", "-M", "none",
"-qmp", monarg, "-qmp", monarg,
"-pidfile", pidfile,
"-daemonize",
NULL); NULL);
virCommandAddEnvPassCommon(cmd); virCommandAddEnvPassCommon(cmd);
virCommandClearCaps(cmd); virCommandClearCaps(cmd);
hookData.runUid = runUid;
hookData.runGid = runGid;
virCommandSetPreExecHook(cmd, qemuCapsHook, &hookData);
virCommandSetPidFile(cmd, pidfile);
virCommandDaemonize(cmd);
if (virCommandRun(cmd, &status) < 0) if (virCommandRun(cmd, &status) < 0)
goto cleanup; goto cleanup;
...@@ -2410,7 +2451,9 @@ cleanup: ...@@ -2410,7 +2451,9 @@ cleanup:
qemuCapsPtr qemuCapsNewForBinary(const char *binary, qemuCapsPtr qemuCapsNewForBinary(const char *binary,
const char *libDir, const char *libDir,
const char *runDir) const char *runDir,
uid_t runUid,
gid_t runGid)
{ {
qemuCapsPtr caps = qemuCapsNew(); qemuCapsPtr caps = qemuCapsNew();
struct stat sb; struct stat sb;
...@@ -2438,11 +2481,11 @@ qemuCapsPtr qemuCapsNewForBinary(const char *binary, ...@@ -2438,11 +2481,11 @@ qemuCapsPtr qemuCapsNewForBinary(const char *binary,
goto error; goto error;
} }
if ((rv = qemuCapsInitQMP(caps, libDir, runDir)) < 0) if ((rv = qemuCapsInitQMP(caps, libDir, runDir, runUid, runGid)) < 0)
goto error; goto error;
if (!caps->usedQMP && if (!caps->usedQMP &&
qemuCapsInitHelp(caps) < 0) qemuCapsInitHelp(caps, runUid, runGid) < 0)
goto error; goto error;
return caps; return caps;
...@@ -2478,7 +2521,8 @@ qemuCapsHashDataFree(void *payload, const void *key ATTRIBUTE_UNUSED) ...@@ -2478,7 +2521,8 @@ qemuCapsHashDataFree(void *payload, const void *key ATTRIBUTE_UNUSED)
qemuCapsCachePtr qemuCapsCachePtr
qemuCapsCacheNew(const char *libDir, const char *runDir) qemuCapsCacheNew(const char *libDir, const char *runDir,
uid_t runUid, gid_t runGid)
{ {
qemuCapsCachePtr cache; qemuCapsCachePtr cache;
...@@ -2502,6 +2546,9 @@ qemuCapsCacheNew(const char *libDir, const char *runDir) ...@@ -2502,6 +2546,9 @@ qemuCapsCacheNew(const char *libDir, const char *runDir)
goto error; goto error;
} }
cache->runUid = runUid;
cache->runGid = runGid;
return cache; return cache;
error: error:
...@@ -2526,7 +2573,8 @@ qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary) ...@@ -2526,7 +2573,8 @@ qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary)
if (!ret) { if (!ret) {
VIR_DEBUG("Creating capabilities for %s", VIR_DEBUG("Creating capabilities for %s",
binary); binary);
ret = qemuCapsNewForBinary(binary, cache->libDir, cache->runDir); ret = qemuCapsNewForBinary(binary, cache->libDir, cache->runDir,
cache->runUid, cache->runGid);
if (ret) { if (ret) {
VIR_DEBUG("Caching capabilities %p for %s", VIR_DEBUG("Caching capabilities %p for %s",
ret, binary); ret, binary);
......
...@@ -169,7 +169,9 @@ qemuCapsPtr qemuCapsNew(void); ...@@ -169,7 +169,9 @@ qemuCapsPtr qemuCapsNew(void);
qemuCapsPtr qemuCapsNewCopy(qemuCapsPtr caps); qemuCapsPtr qemuCapsNewCopy(qemuCapsPtr caps);
qemuCapsPtr qemuCapsNewForBinary(const char *binary, qemuCapsPtr qemuCapsNewForBinary(const char *binary,
const char *libDir, const char *libDir,
const char *runDir); const char *runDir,
uid_t runUid,
gid_t runGid);
int qemuCapsProbeQMP(qemuCapsPtr caps, int qemuCapsProbeQMP(qemuCapsPtr caps,
qemuMonitorPtr mon); qemuMonitorPtr mon);
...@@ -207,7 +209,8 @@ int qemuCapsGetMachineTypesCaps(qemuCapsPtr caps, ...@@ -207,7 +209,8 @@ int qemuCapsGetMachineTypesCaps(qemuCapsPtr caps,
bool qemuCapsIsValid(qemuCapsPtr caps); bool qemuCapsIsValid(qemuCapsPtr caps);
qemuCapsCachePtr qemuCapsCacheNew(const char *libDir, const char *runDir); qemuCapsCachePtr qemuCapsCacheNew(const char *libDir, const char *runDir,
uid_t uid, gid_t gid);
qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary); qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary);
qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary); qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary);
void qemuCapsCacheFree(qemuCapsCachePtr cache); void qemuCapsCacheFree(qemuCapsCachePtr cache);
......
...@@ -787,7 +787,9 @@ qemuStartup(int privileged) { ...@@ -787,7 +787,9 @@ qemuStartup(int privileged) {
goto error; goto error;
qemu_driver->capsCache = qemuCapsCacheNew(qemu_driver->libDir, qemu_driver->capsCache = qemuCapsCacheNew(qemu_driver->libDir,
qemu_driver->stateDir); qemu_driver->stateDir,
qemu_driver->user,
qemu_driver->group);
if (!qemu_driver->capsCache) if (!qemu_driver->capsCache)
goto error; goto error;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册