qemu: Avoid using stale data in virDomainGetBlockInfo

CVE-2013-6458

Generally, every API that is going to begin a job should do that before
fetching data from vm->def. However, qemuDomainGetBlockInfo does not
know whether it will have to start a job or not before checking vm->def.
To avoid using disk alias that might have been freed while we were
waiting for a job, we use its copy. In case the disk was removed in the
meantime, we will fail with "cannot find statistics for device '...'"
error message.

(cherry picked from commit b799259583bd65c0b2f5042e6c3ff19637ade881)

Conflicts:
	src/qemu/qemu_driver.c - VIR_STRDUP not backported, context
This commit is contained in:
Jiri Denemark 2013-12-20 14:50:02 +01:00 committed by Eric Blake
parent 561b03f916
commit 324279f2c8

View File

@ -9210,10 +9210,12 @@ cleanup:
} }
static int qemuDomainGetBlockInfo(virDomainPtr dom, static int
const char *path, qemuDomainGetBlockInfo(virDomainPtr dom,
virDomainBlockInfoPtr info, const char *path,
unsigned int flags) { virDomainBlockInfoPtr info,
unsigned int flags)
{
virQEMUDriverPtr driver = dom->conn->privateData; virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
int ret = -1; int ret = -1;
@ -9224,6 +9226,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
struct stat sb; struct stat sb;
int i; int i;
int format; int format;
char *alias = NULL;
virCheckFlags(0, -1); virCheckFlags(0, -1);
@ -9327,13 +9330,18 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
virDomainObjIsActive(vm)) { virDomainObjIsActive(vm)) {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
if (!(alias = strdup(disk->info.alias))) {
virReportOOMError();
goto cleanup;
}
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
goto cleanup; goto cleanup;
if (virDomainObjIsActive(vm)) { if (virDomainObjIsActive(vm)) {
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorGetBlockExtent(priv->mon, ret = qemuMonitorGetBlockExtent(priv->mon,
disk->info.alias, alias,
&info->allocation); &info->allocation);
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
} else { } else {
@ -9347,6 +9355,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
} }
cleanup: cleanup:
VIR_FREE(alias);
virStorageFileFreeMetadata(meta); virStorageFileFreeMetadata(meta);
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
if (vm) if (vm)