From da0d82d15fd86ca3ed28ec2820fdb824cf92ae91 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 10 Oct 2016 15:46:25 +0200 Subject: [PATCH] conf: Sanitize cpu topology numbers Make sure that the topology results into a sane number of cpus (up to UINT_MAX) so that it can be sanely compared to the vcpu count of the VM. Additionally the helper added in this patch allows to fetch the total number the topology results to so that it does not have to be reimplemented later. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1378290 --- src/conf/domain_conf.c | 39 +++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 1 + 3 files changed, 42 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f562323657..44752b948d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1570,6 +1570,42 @@ virDomainDefGetVcpuPinInfoHelper(virDomainDefPtr def, } +/** + * virDomainDeGetVcpusTopology: + * @def: domain definition + * @maxvcpus: optionally filled with number of vcpus the domain topology describes + * + * Calculates and validates that the vcpu topology is in sane bounds and + * optionally returns the total number of vcpus described by given topology. + * + * Returns 0 on success, 1 if topology is not configured and -1 on error. + */ +int +virDomainDefGetVcpusTopology(const virDomainDef *def, + unsigned int *maxvcpus) +{ + unsigned long long tmp; + + if (!def->cpu || def->cpu->sockets == 0) + return 1; + + tmp = def->cpu->sockets; + + /* multiplication of 32bit numbers fits into a 64bit variable */ + if ((tmp *= def->cpu->cores) > UINT_MAX || + (tmp *= def->cpu->threads) > UINT_MAX) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("cpu topology results in more than %u cpus"), UINT_MAX); + return -1; + } + + if (maxvcpus) + *maxvcpus = tmp; + + return 0; +} + + virDomainDiskDefPtr virDomainDiskDefNew(virDomainXMLOptionPtr xmlopt) { @@ -4786,6 +4822,9 @@ virDomainDefValidateInternal(const virDomainDef *def) if (virDomainDefCheckDuplicateDiskInfo(def) < 0) return -1; + if (virDomainDefGetVcpusTopology(def, NULL) < 0) + return -1; + return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a70bc2182a..54c9502ce4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2488,6 +2488,8 @@ virBitmapPtr virDomainDefGetOnlineVcpumap(const virDomainDef *def); virDomainVcpuDefPtr virDomainDefGetVcpu(virDomainDefPtr def, unsigned int vcpu) ATTRIBUTE_RETURN_CHECK; void virDomainDefVcpuOrderClear(virDomainDefPtr def); +int virDomainDefGetVcpusTopology(const virDomainDef *def, + unsigned int *maxvcpus); virDomainObjPtr virDomainObjNew(virDomainXMLOptionPtr caps) ATTRIBUTE_NONNULL(1); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b88e903744..11a90b1874 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -247,6 +247,7 @@ virDomainDefGetVcpu; virDomainDefGetVcpuPinInfoHelper; virDomainDefGetVcpus; virDomainDefGetVcpusMax; +virDomainDefGetVcpusTopology; virDomainDefHasDeviceAddress; virDomainDefHasMemballoon; virDomainDefHasMemoryHotplug;