diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h index 6972834175..4caed94a77 100644 --- a/include/libvirt/libvirt-host.h +++ b/include/libvirt/libvirt-host.h @@ -754,6 +754,8 @@ typedef enum { typedef enum { VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE = (1 << 0), /* treat incompatible CPUs as failure */ + VIR_CONNECT_COMPARE_CPU_VALIDATE_XML = (1 << 1), /* validate the xml + document */ } virConnectCompareCPUFlags; int virConnectCompareCPU(virConnectPtr conn, diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index 91f41aa238..78c3241293 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -1441,14 +1441,17 @@ bhyveConnectCompareCPU(virConnectPtr conn, int ret = VIR_CPU_COMPARE_ERROR; virCapsPtr caps = NULL; bool failIncompatible; + bool validateXML; - virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE, + virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE | + VIR_CONNECT_COMPARE_CPU_VALIDATE_XML, VIR_CPU_COMPARE_ERROR); if (virConnectCompareCPUEnsureACL(conn) < 0) goto cleanup; failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE); + validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML); if (!(caps = bhyveDriverGetCapabilities(driver))) goto cleanup; @@ -1464,7 +1467,7 @@ bhyveConnectCompareCPU(virConnectPtr conn, } } else { ret = virCPUCompareXML(caps->host.arch, caps->host.cpu, - xmlDesc, failIncompatible); + xmlDesc, failIncompatible, validateXML); } cleanup: diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index dea950ce68..1910470836 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -20,9 +20,11 @@ #include +#include "configmake.h" #include "virerror.h" #include "viralloc.h" #include "virbuffer.h" +#include "virfile.h" #include "cpu_conf.h" #include "domain_conf.h" #include "virstring.h" @@ -281,7 +283,8 @@ virCPUDefCopy(const virCPUDef *cpu) int virCPUDefParseXMLString(const char *xml, virCPUType type, - virCPUDefPtr *cpu) + virCPUDefPtr *cpu, + bool validateXML) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; @@ -295,7 +298,7 @@ virCPUDefParseXMLString(const char *xml, if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt))) goto cleanup; - if (virCPUDefParseXML(ctxt, NULL, type, cpu) < 0) + if (virCPUDefParseXML(ctxt, NULL, type, cpu, validateXML) < 0) goto cleanup; ret = 0; @@ -323,7 +326,8 @@ int virCPUDefParseXML(xmlXPathContextPtr ctxt, const char *xpath, virCPUType type, - virCPUDefPtr *cpu) + virCPUDefPtr *cpu, + bool validateXML) { g_autoptr(virCPUDef) def = NULL; g_autofree xmlNodePtr *nodes = NULL; @@ -348,6 +352,19 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, return -1; } + if (validateXML) { + g_autofree char *schemafile = NULL; + + if (!(schemafile = virFileFindResource("cpu.rng", + abs_top_srcdir "/docs/schemas", + PKGDATADIR "/schemas"))) + return -1; + + if (virXMLValidateNodeAgainstSchema(schemafile, ctxt->doc, + ctxt->node) < 0) + return -1; + } + def = virCPUDefNew(); if (type == VIR_CPU_TYPE_AUTO) { @@ -1146,7 +1163,7 @@ virCPUDefListParse(const char **xmlCPUs, if (!(doc = virXMLParseStringCtxt(xmlCPUs[i], _("(CPU_definition)"), &ctxt))) goto error; - if (virCPUDefParseXML(ctxt, NULL, cpuType, &cpus[i]) < 0) + if (virCPUDefParseXML(ctxt, NULL, cpuType, &cpus[i], false) < 0) goto error; xmlXPathFreeContext(ctxt); diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 24c51e3a63..3ef14b7932 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -192,13 +192,15 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu); int virCPUDefParseXMLString(const char *xml, virCPUType type, - virCPUDefPtr *cpu); + virCPUDefPtr *cpu, + bool validateXML); int virCPUDefParseXML(xmlXPathContextPtr ctxt, const char *xpath, virCPUType mode, - virCPUDefPtr *cpu); + virCPUDefPtr *cpu, + bool validateXML); bool virCPUDefIsEqual(virCPUDefPtr src, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 175b632a38..c003b5c030 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -21917,7 +21917,8 @@ virDomainDefParseXML(xmlDocPtr xml, if (virDomainDefTunablesParse(def, ctxt, xmlopt, flags) < 0) goto error; - if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu) < 0) + if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu, + false) < 0) goto error; if (virDomainNumaDefParseXML(def->numa, ctxt) < 0) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 188c5d86b5..bf94811960 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -109,14 +109,15 @@ virCPUCompareResult virCPUCompareXML(virArch arch, virCPUDefPtr host, const char *xml, - bool failIncompatible) + bool failIncompatible, + bool validateXML) { g_autoptr(virCPUDef) cpu = NULL; VIR_DEBUG("arch=%s, host=%p, xml=%s", virArchToString(arch), host, NULLSTR(xml)); - if (virCPUDefParseXMLString(xml, VIR_CPU_TYPE_AUTO, &cpu) < 0) + if (virCPUDefParseXMLString(xml, VIR_CPU_TYPE_AUTO, &cpu, validateXML) < 0) return VIR_CPU_COMPARE_ERROR; return virCPUCompare(arch, host, cpu, failIncompatible); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index ba8fdd07ba..cc2d132275 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -153,7 +153,8 @@ virCPUCompareResult virCPUCompareXML(virArch arch, virCPUDefPtr host, const char *xml, - bool failIncompatible); + bool failIncompatible, + bool validateXML); virCPUCompareResult virCPUCompare(virArch arch, diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index e28c649688..824ed60dfd 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -6529,19 +6529,22 @@ libxlConnectCompareCPU(virConnectPtr conn, libxlDriverConfigPtr cfg; int ret = VIR_CPU_COMPARE_ERROR; bool failIncompatible; + bool validateXML; - virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE, + virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE | + VIR_CONNECT_COMPARE_CPU_VALIDATE_XML, VIR_CPU_COMPARE_ERROR); if (virConnectCompareCPUEnsureACL(conn) < 0) return ret; failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE); + validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML); cfg = libxlDriverConfigGet(driver); ret = virCPUCompareXML(cfg->caps->host.arch, cfg->caps->host.cpu, - xmlDesc, failIncompatible); + xmlDesc, failIncompatible, validateXML); virObjectUnref(cfg); return ret; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 0687f4584c..9623123d3c 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3130,7 +3130,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, qemuDomainSetPrivatePathsOld(driver, vm); - if (virCPUDefParseXML(ctxt, "./cpu", VIR_CPU_TYPE_GUEST, &priv->origCPU) < 0) + if (virCPUDefParseXML(ctxt, "./cpu", VIR_CPU_TYPE_GUEST, &priv->origCPU, + false) < 0) goto error; priv->chardevStdioLogd = virXPathBoolean("boolean(./chardevStdioLogd)", @@ -9997,7 +9998,7 @@ qemuDomainSaveCookieParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED, return -1; if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, - &cookie->cpu) < 0) + &cookie->cpu, false) < 0) return -1; cookie->slirpHelper = virXPathBoolean("boolean(./slirpHelper)", ctxt) > 0; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5aaa969409..8ef812cd94 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12202,20 +12202,23 @@ qemuConnectCompareCPU(virConnectPtr conn, virQEMUDriverPtr driver = conn->privateData; g_autoptr(virCPUDef) cpu = NULL; bool failIncompatible; + bool validateXML; - virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE, + virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE | + VIR_CONNECT_COMPARE_CPU_VALIDATE_XML, VIR_CPU_COMPARE_ERROR); if (virConnectCompareCPUEnsureACL(conn) < 0) return VIR_CPU_COMPARE_ERROR; failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE); + validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML); if (!(cpu = virQEMUDriverGetHostCPU(driver))) return VIR_CPU_COMPARE_ERROR; return virCPUCompareXML(driver->hostarch, cpu, - xmlDesc, failIncompatible); + xmlDesc, failIncompatible, validateXML); } @@ -12270,18 +12273,21 @@ qemuConnectCompareHypervisorCPU(virConnectPtr conn, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autoptr(virQEMUCaps) qemuCaps = NULL; bool failIncompatible; + bool validateXML; virCPUDefPtr hvCPU; virCPUDefPtr cpu = NULL; virArch arch; virDomainVirtType virttype; - virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE, + virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE | + VIR_CONNECT_COMPARE_CPU_VALIDATE_XML, VIR_CPU_COMPARE_ERROR); if (virConnectCompareHypervisorCPUEnsureACL(conn) < 0) goto cleanup; failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE); + validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML); qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache, emulator, @@ -12305,10 +12311,12 @@ qemuConnectCompareHypervisorCPU(virConnectPtr conn, } if (ARCH_IS_X86(arch)) { - ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible); + ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible, + validateXML); } else if (ARCH_IS_S390(arch) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_COMPARISON)) { - if (virCPUDefParseXMLString(xmlCPU, VIR_CPU_TYPE_AUTO, &cpu) < 0) + if (virCPUDefParseXMLString(xmlCPU, VIR_CPU_TYPE_AUTO, &cpu, + validateXML) < 0) goto cleanup; if (!cpu->model) { diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c index 91694000d8..abe797759d 100644 --- a/src/qemu/qemu_migration_cookie.c +++ b/src/qemu/qemu_migration_cookie.c @@ -1263,7 +1263,8 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, return -1; if (flags & QEMU_MIGRATION_COOKIE_CPU && - virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &mig->cpu) < 0) + virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &mig->cpu, + false) < 0) return -1; if (flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT && diff --git a/tests/cputest.c b/tests/cputest.c index 383da94938..78a7f2437a 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -81,7 +81,7 @@ cpuTestLoadXML(virArch arch, const char *name) if (!(doc = virXMLParseFileCtxt(xml, &ctxt))) goto cleanup; - virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_AUTO, &cpu); + virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_AUTO, &cpu, false); cleanup: xmlXPathFreeContext(ctxt); @@ -120,7 +120,8 @@ cpuTestLoadMultiXML(virArch arch, for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_HOST, &cpus[i]) < 0) + if (virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_HOST, &cpus[i], + false) < 0) goto cleanup_cpus; }