From baeefe03279dc4b39e19ae61153aad864f311254 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 21 Jul 2023 12:57:39 +0200 Subject: [PATCH] qemu_domain: Partially validate memory amounts when auto-adding NUMA node When automatically adding a NUMA node (qemuDomainDefNumaAutoAdd()) the memory size of the node is computed as: total_memory - sum(memory devices) And we have a nice helper for that: virDomainDefGetMemoryInitial() so it looks logical to just call it. Except, this code runs in post parse callback, i.e. memory sizes were not validated and it may happen that the sum is greater than the total memory. This would be caught by virDomainDefPostParseMemory() but that runs only after driver specific callbacks (i.e. after qemuDomainDefNumaAutoAdd()) and because the domain config was changed and memory was increased to this huge number no error is caught. So let's do what virDomainDefGetMemoryInitial() would do, but with error checking. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2216236 Fixes: f5d4f5c8ee44e9f1939070afcc5381bdd5545e50 Signed-off-by: Michal Privoznik Reviewed-by: Kristina Hanicova --- src/qemu/qemu_domain.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6eea8a9fa5..029238a9d7 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4812,7 +4812,7 @@ qemuDomainDefNumaAutoAdd(virDomainDef *def, unsigned int parseFlags) { bool abiUpdate = !!(parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE); - unsigned long long initialMem; + unsigned long long nodeMem; size_t i; if (!abiUpdate || @@ -4821,17 +4821,24 @@ qemuDomainDefNumaAutoAdd(virDomainDef *def, return 0; } - initialMem = virDomainDefGetMemoryInitial(def); + nodeMem = virDomainDefGetMemoryTotal(def); if (!def->numa) def->numa = virDomainNumaNew(); virDomainNumaSetNodeCount(def->numa, 1); - virDomainNumaSetNodeMemorySize(def->numa, 0, initialMem); for (i = 0; i < def->nmems; i++) { virDomainMemoryDef *mem = def->mems[i]; + if (mem->size > nodeMem) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Total size of memory devices exceeds the total memory size")); + return -1; + } + + nodeMem -= mem->size; + switch (mem->model) { case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: @@ -4848,6 +4855,8 @@ qemuDomainDefNumaAutoAdd(virDomainDef *def, } } + virDomainNumaSetNodeMemorySize(def->numa, 0, nodeMem); + return 0; }