qemu: fix a bug in numatune

When setting numa nodeset for a domain which has no nodeset set
before, libvirtd crashes by dereferencing the pointer to the old
nodemask which is null in that case.
This commit is contained in:
Hu Tao 2012-01-04 17:41:43 +08:00 committed by Eric Blake
parent 820a2159e9
commit 6b780f744b

View File

@ -6679,6 +6679,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
} }
} else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) { } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
int rc; int rc;
bool savedmask;
char oldnodemask[VIR_DOMAIN_CPUMASK_LEN]; char oldnodemask[VIR_DOMAIN_CPUMASK_LEN];
if (param->type != VIR_TYPED_PARAM_STRING) { if (param->type != VIR_TYPED_PARAM_STRING) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s", qemuReportError(VIR_ERR_INVALID_ARG, "%s",
@ -6707,28 +6708,56 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
/* update vm->def here so that dumpxml can read the new /* update vm->def here so that dumpxml can read the new
* values from vm->def. */ * values from vm->def. */
memcpy(oldnodemask, vm->def->numatune.memory.nodemask, savedmask = false;
VIR_DOMAIN_CPUMASK_LEN); if (!vm->def->numatune.memory.nodemask) {
if (VIR_ALLOC_N(vm->def->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) {
virReportOOMError();
ret = -1;
goto cleanup;
}
} else {
memcpy(oldnodemask, vm->def->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN);
savedmask = true;
}
if (virDomainCpuSetParse(params[i].value.s, if (virDomainCpuSetParse(params[i].value.s,
0, 0,
vm->def->numatune.memory.nodemask, vm->def->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) { VIR_DOMAIN_CPUMASK_LEN) < 0) {
memcpy(vm->def->numatune.memory.nodemask, if (savedmask)
oldnodemask, VIR_DOMAIN_CPUMASK_LEN); memcpy(vm->def->numatune.memory.nodemask,
oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
else
VIR_FREE(vm->def->numatune.memory.nodemask);
ret = -1; ret = -1;
continue; continue;
} }
} }
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
memcpy(oldnodemask, persistentDef->numatune.memory.nodemask, savedmask = false;
VIR_DOMAIN_CPUMASK_LEN); if (!persistentDef->numatune.memory.nodemask) {
if (VIR_ALLOC_N(persistentDef->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) {
virReportOOMError();
ret = -1;
goto cleanup;
}
} else {
memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN);
savedmask = true;
}
if (virDomainCpuSetParse(params[i].value.s, if (virDomainCpuSetParse(params[i].value.s,
0, 0,
persistentDef->numatune.memory.nodemask, persistentDef->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) { VIR_DOMAIN_CPUMASK_LEN) < 0) {
memcpy(persistentDef->numatune.memory.nodemask, if (savedmask)
oldnodemask, VIR_DOMAIN_CPUMASK_LEN); memcpy(persistentDef->numatune.memory.nodemask,
oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
else
VIR_FREE(persistentDef->numatune.memory.nodemask);
ret = -1; ret = -1;
continue; continue;
} }