diff --git a/SOURCES/libvirt-qemu-Fix-crash-on-incoming-migration.patch b/SOURCES/libvirt-qemu-Fix-crash-on-incoming-migration.patch new file mode 100644 index 0000000..be2a6e5 --- /dev/null +++ b/SOURCES/libvirt-qemu-Fix-crash-on-incoming-migration.patch @@ -0,0 +1,45 @@ +From f8aa84166ddd8a603cce1ec02ff7630e78bb1a9b Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:37 +0200 +Subject: [PATCH] qemu: Fix crash on incoming migration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the first stage of incoming migration (qemuMigrationDstPrepareAny) we +call qemuMigrationEatCookie when there's no vm object created yet and +thus we don't have any private data to pass. + +Broken by me in commit v5.6.0-109-gbf15b145ec. + +Signed-off-by: Jiri Denemark +Reviewed-by: Erik Skultety +(cherry picked from commit 69b1ecde25aef6545cc077fe3c92ba19f1623828) + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <7e7b2059ff2bcbc082c3fdd8f6723b1771db289b.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_migration_cookie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c +index b9933b9e04..8c8df89b1b 100644 +--- a/src/qemu/qemu_migration_cookie.c ++++ b/src/qemu/qemu_migration_cookie.c +@@ -1503,7 +1503,7 @@ qemuMigrationEatCookie(virQEMUDriverPtr driver, + if (cookiein && cookieinlen && + qemuMigrationCookieXMLParseStr(mig, + driver, +- priv->qemuCaps, ++ priv ? priv->qemuCaps : NULL, + cookiein, + flags) < 0) + goto error; +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefCopy.patch b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefCopy.patch new file mode 100644 index 0000000..7df7726 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefCopy.patch @@ -0,0 +1,504 @@ +From bdb0a40645dc91fe4fea4327634e118cc22c3c1c Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:33 +0200 +Subject: [PATCH] qemu: Pass correct qemuCaps to virDomainDefCopy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +Several general functions from domain_conf.c were lazily passing NULL as +the parseOpaque pointer instead of letting their callers pass the right +data. This patch fixes all paths leading to virDomainDefCopy to do the +right thing. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit bbcfa07bea4fbe2fe8a51f99f20c77ddefd2d40d) + +Conflicts: + src/lxc/lxc_driver.c + - context + + src/qemu/qemu_driver.c + - qemuDomainAttachDeviceLiveAndConfig is quite different + - context in qemuDomainRevertToSnapshot + - ProcessAttach API was removed upstream + + src/uml/uml_driver.c + - uml driver was removed upstream + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 18 +++++++++++------- + src/conf/domain_conf.h | 9 ++++++--- + src/libxl/libxl_domain.c | 2 +- + src/libxl/libxl_driver.c | 10 +++++----- + src/libxl/libxl_migration.c | 2 +- + src/lxc/lxc_driver.c | 8 ++++---- + src/lxc/lxc_process.c | 2 +- + src/qemu/qemu_driver.c | 28 ++++++++++++++++++++-------- + src/qemu/qemu_migration.c | 4 +++- + src/qemu/qemu_process.c | 4 ++-- + src/test/test_driver.c | 2 +- + src/uml/uml_driver.c | 2 +- + tests/qemuhotplugtest.c | 2 +- + 13 files changed, 57 insertions(+), 36 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index aaf6a6bab1..0fdf1742fd 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -3374,7 +3374,8 @@ virDomainObjWaitUntil(virDomainObjPtr vm, + int + virDomainObjSetDefTransient(virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, +- virDomainObjPtr domain) ++ virDomainObjPtr domain, ++ void *parseOpaque) + { + int ret = -1; + +@@ -3384,7 +3385,8 @@ virDomainObjSetDefTransient(virCapsPtr caps, + if (domain->newDef) + return 0; + +- if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt, NULL, false))) ++ if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt, ++ parseOpaque, false))) + goto out; + + ret = 0; +@@ -3423,10 +3425,11 @@ virDomainObjRemoveTransientDef(virDomainObjPtr domain) + virDomainDefPtr + virDomainObjGetPersistentDef(virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, +- virDomainObjPtr domain) ++ virDomainObjPtr domain, ++ void *parseOpaque) + { + if (virDomainObjIsActive(domain) && +- virDomainObjSetDefTransient(caps, xmlopt, domain) < 0) ++ virDomainObjSetDefTransient(caps, xmlopt, domain, parseOpaque) < 0) + return NULL; + + if (domain->newDef) +@@ -29180,12 +29183,13 @@ virDomainDefCopy(virDomainDefPtr src, + virDomainDefPtr + virDomainObjCopyPersistentDef(virDomainObjPtr dom, + virCapsPtr caps, +- virDomainXMLOptionPtr xmlopt) ++ virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque) + { + virDomainDefPtr cur; + +- cur = virDomainObjGetPersistentDef(caps, xmlopt, dom); +- return virDomainDefCopy(cur, caps, xmlopt, NULL, false); ++ cur = virDomainObjGetPersistentDef(caps, xmlopt, dom, parseOpaque); ++ return virDomainDefCopy(cur, caps, xmlopt, parseOpaque, false); + } + + +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 2d272f907f..9e4fed6d4e 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2940,12 +2940,14 @@ void virDomainObjAssignDef(virDomainObjPtr domain, + virDomainDefPtr *oldDef); + int virDomainObjSetDefTransient(virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, +- virDomainObjPtr domain); ++ virDomainObjPtr domain, ++ void *parseOpaque); + void virDomainObjRemoveTransientDef(virDomainObjPtr domain); + virDomainDefPtr + virDomainObjGetPersistentDef(virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, +- virDomainObjPtr domain); ++ virDomainObjPtr domain, ++ void *parseOpaque); + + int virDomainObjUpdateModificationImpact(virDomainObjPtr vm, + unsigned int *flags); +@@ -2966,7 +2968,8 @@ virDomainDefPtr virDomainDefCopy(virDomainDefPtr src, + bool migratable); + virDomainDefPtr virDomainObjCopyPersistentDef(virDomainObjPtr dom, + virCapsPtr caps, +- virDomainXMLOptionPtr xmlopt); ++ virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque); + + typedef enum { + /* parse internal domain status information */ +diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c +index 2ab78ac9a5..f52540e6a7 100644 +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -1208,7 +1208,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver, + VIR_FREE(managed_save_path); + } + +- if (virDomainObjSetDefTransient(cfg->caps, driver->xmlopt, vm) < 0) ++ if (virDomainObjSetDefTransient(cfg->caps, driver->xmlopt, vm, NULL) < 0) + goto cleanup; + + /* Run an early hook to set-up missing devices */ +diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c +index 5a5e792957..be6b66ce7e 100644 +--- a/src/libxl/libxl_driver.c ++++ b/src/libxl/libxl_driver.c +@@ -1461,7 +1461,7 @@ virDomainLiveConfigHelperMethod(virCapsPtr caps, + return -1; + + if (*flags & VIR_DOMAIN_AFFECT_CONFIG) { +- if (!(*persistentDef = virDomainObjGetPersistentDef(caps, xmlopt, dom))) { ++ if (!(*persistentDef = virDomainObjGetPersistentDef(caps, xmlopt, dom, NULL))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Get persistent config failed")); + return -1; +@@ -2147,7 +2147,7 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, + goto endjob; + } + +- if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm))) ++ if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm, NULL))) + goto endjob; + + maplen = VIR_CPU_MAPLEN(nvcpus); +@@ -3961,7 +3961,7 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + + /* Make a copy for updated domain. */ + if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, +- driver->xmlopt))) ++ driver->xmlopt, NULL))) + goto endjob; + + if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0) +@@ -4051,7 +4051,7 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + + /* Make a copy for updated domain. */ + if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, +- driver->xmlopt))) ++ driver->xmlopt, NULL))) + goto endjob; + + if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0) +@@ -4138,7 +4138,7 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + + /* Make a copy for updated domain. */ + if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, +- driver->xmlopt))) ++ driver->xmlopt, NULL))) + goto cleanup; + + if ((ret = libxlDomainUpdateDeviceConfig(vmdef, dev)) < 0) +diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c +index b2e5847c58..f207bd7b02 100644 +--- a/src/libxl/libxl_migration.c ++++ b/src/libxl/libxl_migration.c +@@ -1293,7 +1293,7 @@ libxlDomainMigrationDstFinish(virConnectPtr dconn, + + vm->persistent = 1; + if (!(vmdef = virDomainObjGetPersistentDef(cfg->caps, +- driver->xmlopt, vm))) ++ driver->xmlopt, vm, NULL))) + goto cleanup; + + if (virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef) < 0) +diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c +index f9794e0655..b182fa3759 100644 +--- a/src/lxc/lxc_driver.c ++++ b/src/lxc/lxc_driver.c +@@ -1936,7 +1936,7 @@ lxcDomainSetSchedulerParametersFlags(virDomainPtr dom, + + if (persistentDef) { + /* Make a copy for updated domain. */ +- persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL); + if (!persistentDefCopy) + goto endjob; + } +@@ -4755,7 +4755,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL); + if (!vmdef) + goto endjob; + +@@ -4870,7 +4870,7 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL); + if (!vmdef) + goto endjob; + +@@ -4961,7 +4961,7 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL); + if (!vmdef) + goto endjob; + +diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c +index 14502e12fe..d40c7acaaa 100644 +--- a/src/lxc/lxc_process.c ++++ b/src/lxc/lxc_process.c +@@ -1274,7 +1274,7 @@ int virLXCProcessStart(virConnectPtr conn, + * report implicit runtime defaults in the XML, like vnc listen/socket + */ + VIR_DEBUG("Setting current domain def as transient"); +- if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm) < 0) ++ if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, NULL) < 0) + goto cleanup; + + /* Run an early hook to set-up missing devices */ +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 3f8530eb0e..82371b9a66 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -8379,6 +8379,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, + const char *xml, + unsigned int flags) + { ++ qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr vmdef = NULL; + virQEMUDriverConfigPtr cfg = NULL; + virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; +@@ -8417,7 +8418,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, priv->qemuCaps); + if (!vmdef) + goto cleanup; + +@@ -8520,6 +8521,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + { + virQEMUDriverPtr driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; ++ qemuDomainObjPrivatePtr priv; + virDomainDefPtr vmdef = NULL; + virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; + bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; +@@ -8542,6 +8544,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + if (!(vm = qemuDomObjFromDomain(dom))) + goto cleanup; + ++ priv = vm->privateData; ++ + if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + +@@ -8574,7 +8578,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, ++ priv->qemuCaps); + if (!vmdef) + goto endjob; + +@@ -8632,6 +8637,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver, + const char *xml, + unsigned int flags) + { ++ qemuDomainObjPrivatePtr priv = vm->privateData; + virCapsPtr caps = NULL; + virQEMUDriverConfigPtr cfg = NULL; + virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; +@@ -8670,7 +8676,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver, + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + /* Make a copy for updated domain. */ +- vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); ++ vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, priv->qemuCaps); + if (!vmdef) + goto cleanup; + +@@ -8726,6 +8732,7 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver, + const char *alias, + unsigned int flags) + { ++ qemuDomainObjPrivatePtr priv = vm->privateData; + virCapsPtr caps = NULL; + virQEMUDriverConfigPtr cfg = NULL; + virDomainDefPtr def = NULL; +@@ -8752,7 +8759,8 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver, + if (persistentDef) { + virDomainDeviceDef dev; + +- if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt))) ++ if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, ++ priv->qemuCaps))) + goto cleanup; + + if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0) +@@ -10368,7 +10376,8 @@ qemuDomainSetSchedulerParametersFlags(virDomainPtr dom, + if (persistentDef) { + /* Make a copy for updated domain. */ + if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, +- driver->xmlopt))) ++ driver->xmlopt, ++ priv->qemuCaps))) + goto endjob; + } + +@@ -15975,6 +15984,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + if (!(vm = qemuDomObjFromSnapshot(snapshot))) + goto cleanup; + ++ priv = vm->privateData; + cfg = virQEMUDriverGetConfig(driver); + + if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0) +@@ -16052,7 +16062,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + snap->def->current = true; + if (snap->def->dom) { + config = virDomainDefCopy(snap->def->dom, caps, +- driver->xmlopt, NULL, true); ++ driver->xmlopt, priv->qemuCaps, true); + if (!config) + goto endjob; + } +@@ -16062,7 +16072,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + switch ((virDomainState) snap->def->state) { + case VIR_DOMAIN_RUNNING: + case VIR_DOMAIN_PAUSED: +- priv = vm->privateData; + start_flags |= VIR_QEMU_PROCESS_START_PAUSED; + + /* Transitions 2, 3, 5, 6, 8, 9 */ +@@ -20500,6 +20509,7 @@ qemuDomainGetFSInfo(virDomainPtr dom, + unsigned int flags) + { + virQEMUDriverPtr driver = dom->conn->privateData; ++ qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + qemuAgentPtr agent; + virCapsPtr caps = NULL; +@@ -20511,6 +20521,8 @@ qemuDomainGetFSInfo(virDomainPtr dom, + if (!(vm = qemuDomObjFromDomain(dom))) + return ret; + ++ priv = vm->privateData; ++ + if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + +@@ -20526,7 +20538,7 @@ qemuDomainGetFSInfo(virDomainPtr dom, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto endjob; + +- if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, false))) ++ if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, priv->qemuCaps, false))) + goto endjob; + + agent = qemuDomainObjEnterAgent(vm); +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index f5d77d2508..b7f4110baf 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -4850,6 +4850,7 @@ qemuMigrationDstPersist(virQEMUDriverPtr driver, + bool ignoreSaveError) + { + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); ++ qemuDomainObjPrivatePtr priv = vm->privateData; + virCapsPtr caps = NULL; + virDomainDefPtr vmdef; + virDomainDefPtr oldDef = NULL; +@@ -4864,7 +4865,8 @@ qemuMigrationDstPersist(virQEMUDriverPtr driver, + oldDef = vm->newDef; + vm->newDef = qemuMigrationCookieGetPersistent(mig); + +- if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm))) ++ if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm, ++ priv->qemuCaps))) + goto error; + + if (virDomainSaveConfig(cfg->configDir, driver->caps, vmdef) < 0 && +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 34686b4d92..08e1d91fcc 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -5375,7 +5375,7 @@ qemuProcessInit(virQEMUDriverPtr driver, + * report implicit runtime defaults in the XML, like vnc listen/socket + */ + VIR_DEBUG("Setting current domain def as transient"); +- if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm) < 0) ++ if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, priv->qemuCaps) < 0) + goto cleanup; + + if (flags & VIR_QEMU_PROCESS_START_PRETEND) { +@@ -7314,7 +7314,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, + * report implicit runtime defaults in the XML, like vnc listen/socket + */ + VIR_DEBUG("Setting current domain def as transient"); +- if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm) < 0) ++ if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, NULL) < 0) + goto error; + + vm->def->id = qemuDriverAllocateID(driver); +diff --git a/src/test/test_driver.c b/src/test/test_driver.c +index 5494d51017..1a25b37729 100644 +--- a/src/test/test_driver.c ++++ b/src/test/test_driver.c +@@ -657,7 +657,7 @@ testDomainStartState(testDriverPtr privconn, + + if (virDomainObjSetDefTransient(privconn->caps, + privconn->xmlopt, +- dom) < 0) { ++ dom, NULL) < 0) { + goto cleanup; + } + +diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c +index c77988f01e..796de53d43 100644 +--- a/src/uml/uml_driver.c ++++ b/src/uml/uml_driver.c +@@ -1092,7 +1092,7 @@ static int umlStartVMDaemon(virConnectPtr conn, + * report implicit runtime defaults in the XML, like vnc listen/socket + */ + VIR_DEBUG("Setting current domain def as transient"); +- if (virDomainObjSetDefTransient(driver->caps, driver->xmlopt, vm) < 0) { ++ if (virDomainObjSetDefTransient(driver->caps, driver->xmlopt, vm, NULL) < 0) { + VIR_FORCE_CLOSE(logfd); + return -1; + } +diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c +index bc199685c6..2dbf768e16 100644 +--- a/tests/qemuhotplugtest.c ++++ b/tests/qemuhotplugtest.c +@@ -425,7 +425,7 @@ testQemuHotplugCpuPrepare(const char *test, + + /* create vm->newDef */ + data->vm->persistent = true; +- if (virDomainObjSetDefTransient(caps, driver.xmlopt, data->vm) < 0) ++ if (virDomainObjSetDefTransient(caps, driver.xmlopt, data->vm, NULL) < 0) + goto error; + + priv = data->vm->privateData; +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseNode.patch b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseNode.patch new file mode 100644 index 0000000..1d3fb94 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseNode.patch @@ -0,0 +1,261 @@ +From d563ed75402973b6df254268c17b93edbbaee651 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:35 +0200 +Subject: [PATCH] qemu: Pass correct qemuCaps to virDomainDefParseNode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +Several general snapshot and checkpoint APIs were lazily passing NULL as +the parseOpaque pointer instead of letting their callers pass the right +data. This patch fixes all paths leading to virDomainDefParseNode. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 577a1f98fc84e4152c246695942502ef9a45c7f7) + +Conflicts: + src/conf/checkpoint_conf.c + src/conf/checkpoint_conf.h + src/conf/snapshot_conf.c + src/conf/snapshot_conf.h + src/esx/esx_driver.c + src/qemu/qemu_driver.c + src/test/test_driver.c + src/vbox/vbox_common.c + tests/qemudomaincheckpointxml2xmltest.c + - no checkpoint APIs + - snapshot parsing APIs do not have bool *current parameter + + tests/qemudomainsnapshotxml2xmltest.c + - this is called domainsnapshotxml2xmltest.c downstream + - snapshot parsing APIs do not have bool *current parameter + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/snapshot_conf.c | 9 ++++++--- + src/conf/snapshot_conf.h | 2 ++ + src/esx/esx_driver.c | 2 +- + src/qemu/qemu_driver.c | 10 +++++++--- + src/test/test_driver.c | 3 ++- + src/vbox/vbox_common.c | 4 ++-- + tests/domainsnapshotxml2xmltest.c | 2 +- + 7 files changed, 21 insertions(+), 11 deletions(-) + +diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c +index 9c537ac7d1..75df496201 100644 +--- a/src/conf/snapshot_conf.c ++++ b/src/conf/snapshot_conf.c +@@ -203,6 +203,7 @@ static virDomainSnapshotDefPtr + virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags) + { + virDomainSnapshotDefPtr def = NULL; +@@ -284,7 +285,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt, + goto cleanup; + } + def->dom = virDomainDefParseNode(ctxt->node->doc, domainNode, +- caps, xmlopt, NULL, domainflags); ++ caps, xmlopt, parseOpaque, domainflags); + if (!def->dom) + goto cleanup; + } else { +@@ -389,6 +390,7 @@ virDomainSnapshotDefParseNode(xmlDocPtr xml, + xmlNodePtr root, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags) + { + xmlXPathContextPtr ctxt = NULL; +@@ -406,7 +408,7 @@ virDomainSnapshotDefParseNode(xmlDocPtr xml, + } + + ctxt->node = root; +- def = virDomainSnapshotDefParse(ctxt, caps, xmlopt, flags); ++ def = virDomainSnapshotDefParse(ctxt, caps, xmlopt, parseOpaque, flags); + cleanup: + xmlXPathFreeContext(ctxt); + return def; +@@ -416,6 +418,7 @@ virDomainSnapshotDefPtr + virDomainSnapshotDefParseString(const char *xmlStr, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags) + { + virDomainSnapshotDefPtr ret = NULL; +@@ -425,7 +428,7 @@ virDomainSnapshotDefParseString(const char *xmlStr, + if ((xml = virXMLParse(NULL, xmlStr, _("(domain_snapshot)")))) { + xmlKeepBlanksDefault(keepBlanksDefault); + ret = virDomainSnapshotDefParseNode(xml, xmlDocGetRootElement(xml), +- caps, xmlopt, flags); ++ caps, xmlopt, parseOpaque, flags); + xmlFreeDoc(xml); + } + xmlKeepBlanksDefault(keepBlanksDefault); +diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h +index 20a42bd572..733f1dd071 100644 +--- a/src/conf/snapshot_conf.h ++++ b/src/conf/snapshot_conf.h +@@ -106,11 +106,13 @@ typedef enum { + virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags); + virDomainSnapshotDefPtr virDomainSnapshotDefParseNode(xmlDocPtr xml, + xmlNodePtr root, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags); + void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); + char *virDomainSnapshotDefFormat(const char *domain_uuid, +diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c +index 60aa5fc252..4ef856d71c 100644 +--- a/src/esx/esx_driver.c ++++ b/src/esx/esx_driver.c +@@ -4156,7 +4156,7 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, + return NULL; + + def = virDomainSnapshotDefParseString(xmlDesc, priv->caps, +- priv->xmlopt, 0); ++ priv->xmlopt, NULL, 0); + + if (!def) + return NULL; +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index cc7210c6f4..00213a5f80 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -431,8 +431,12 @@ qemuDomainSnapshotLoad(virDomainObjPtr vm, + int ret = -1; + virCapsPtr caps = NULL; + int direrr; ++ qemuDomainObjPrivatePtr priv; + + virObjectLock(vm); ++ ++ priv = vm->privateData; ++ + if (virAsprintf(&snapDir, "%s/%s", baseDir, vm->def->name) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to allocate memory for " +@@ -472,6 +476,7 @@ qemuDomainSnapshotLoad(virDomainObjPtr vm, + + def = virDomainSnapshotDefParseString(xmlStr, caps, + qemu_driver->xmlopt, ++ priv->qemuCaps, + flags); + if (def == NULL) { + /* Nothing we can do here, skip this one */ +@@ -15312,6 +15317,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, + if (!(vm = qemuDomObjFromDomain(domain))) + goto cleanup; + ++ priv = vm->privateData; + cfg = virQEMUDriverGetConfig(driver); + + if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0) +@@ -15336,7 +15342,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, + parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE; + + if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt, +- parse_flags))) ++ priv->qemuCaps, parse_flags))) + goto cleanup; + + /* reject snapshot names containing slashes or starting with dot as +@@ -15405,8 +15411,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, + + qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE); + +- priv = vm->privateData; +- + if (redefine) { + if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap, + driver->xmlopt, +diff --git a/src/test/test_driver.c b/src/test/test_driver.c +index 1a25b37729..1c7e4f4982 100644 +--- a/src/test/test_driver.c ++++ b/src/test/test_driver.c +@@ -849,6 +849,7 @@ testParseDomainSnapshots(testDriverPtr privconn, + def = virDomainSnapshotDefParseNode(ctxt->doc, node, + privconn->caps, + privconn->xmlopt, ++ NULL, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); +@@ -6403,6 +6404,7 @@ testDomainSnapshotCreateXML(virDomainPtr domain, + if (!(def = virDomainSnapshotDefParseString(xmlDesc, + privconn->caps, + privconn->xmlopt, ++ NULL, + parse_flags))) + goto cleanup; + +@@ -6808,7 +6810,6 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + } + + +- + static virHypervisorDriver testHypervisorDriver = { + .name = "Test", + .connectOpen = testConnectOpen, /* 0.1.1 */ +diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c +index 664650f217..46d2b7afa3 100644 +--- a/src/vbox/vbox_common.c ++++ b/src/vbox/vbox_common.c +@@ -5496,7 +5496,7 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, + VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, NULL); + + if (!(def = virDomainSnapshotDefParseString(xmlDesc, data->caps, +- data->xmlopt, ++ data->xmlopt, NULL, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) + goto cleanup; +@@ -6941,7 +6941,7 @@ vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) + } + def = virDomainSnapshotDefParseString(defXml, + data->caps, +- data->xmlopt, ++ data->xmlopt, NULL, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); + if (!def) { +diff --git a/tests/domainsnapshotxml2xmltest.c b/tests/domainsnapshotxml2xmltest.c +index 5ea0f325de..061da9fbca 100644 +--- a/tests/domainsnapshotxml2xmltest.c ++++ b/tests/domainsnapshotxml2xmltest.c +@@ -96,7 +96,7 @@ testCompareXMLToXMLFiles(const char *inxml, + goto cleanup; + + if (!(def = virDomainSnapshotDefParseString(inXmlData, driver.caps, +- driver.xmlopt, ++ driver.xmlopt, NULL, + flags))) + goto cleanup; + +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseString.patch b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseString.patch new file mode 100644 index 0000000..c54782b --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseString.patch @@ -0,0 +1,65 @@ +From 05516528f7ef69e84eb3edc8a00bc9fba44ea538 Mon Sep 17 00:00:00 2001 +Message-Id: <05516528f7ef69e84eb3edc8a00bc9fba44ea538@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:31 +0200 +Subject: [PATCH] qemu: Pass correct qemuCaps to virDomainDefParseString +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to virDomainDefParseString. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 6e7c33dad7f2f90182c452917f3a555e2c878d42) + +Conflicts: + src/qemu/qemu_driver.c + - snapshots are not based on virDomainMomentDef + - no checkpoint APIs + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <2728b24106e1e361cf9766ea8f9eeec782df6b20.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_driver.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 590596a421..3f8530eb0e 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -3307,7 +3307,8 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, + if (xmlin) { + virDomainDefPtr def = NULL; + +- if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt, NULL, ++ if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt, ++ priv->qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) { + goto endjob; +@@ -15405,7 +15406,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, + if (!(xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, + vm->def, priv->origCPU, + true, true)) || +- !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL, ++ !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt, ++ priv->qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + goto endjob; +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefPostParse.patch b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefPostParse.patch new file mode 100644 index 0000000..6bc638e --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefPostParse.patch @@ -0,0 +1,145 @@ +From f5bfc6725c28833ee0e4cb202e33507cd24ac089 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:34 +0200 +Subject: [PATCH] qemu: Pass correct qemuCaps to virDomainDefPostParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to virDomainDefPostParse. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit c90fb5a828a68512095d80c190c0f491e385438e) + +Conflicts: + src/qemu/qemu_driver.c + - context + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <816c373facf7f779dc22d8a8e6e382cadf5cc2b7.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_driver.c | 17 ++++++++++------- + src/qemu/qemu_process.c | 2 +- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 82371b9a66..cc7210c6f4 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -7881,6 +7881,7 @@ static int + qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, + virDomainDeviceDefPtr dev, + virCapsPtr caps, ++ virQEMUCapsPtr qemuCaps, + unsigned int parse_flags, + virDomainXMLOptionPtr xmlopt) + { +@@ -8070,7 +8071,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, + return -1; + } + +- if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0) ++ if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, qemuCaps) < 0) + return -1; + + return 0; +@@ -8081,6 +8082,7 @@ static int + qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, + virDomainDeviceDefPtr dev, + virCapsPtr caps, ++ virQEMUCapsPtr qemuCaps, + unsigned int parse_flags, + virDomainXMLOptionPtr xmlopt) + { +@@ -8262,7 +8264,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, + return -1; + } + +- if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0) ++ if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, qemuCaps) < 0) + return -1; + + return 0; +@@ -8272,6 +8274,7 @@ static int + qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, + virDomainDeviceDefPtr dev, + virCapsPtr caps, ++ virQEMUCapsPtr qemuCaps, + unsigned int parse_flags, + virDomainXMLOptionPtr xmlopt) + { +@@ -8367,7 +8370,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, + return -1; + } + +- if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0) ++ if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, qemuCaps) < 0) + return -1; + + return 0; +@@ -8426,7 +8429,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, + VIR_DOMAIN_DEVICE_ACTION_ATTACH, + false) < 0) + goto cleanup; +- if ((ret = qemuDomainAttachDeviceConfig(vmdef, dev, caps, ++ if ((ret = qemuDomainAttachDeviceConfig(vmdef, dev, caps, priv->qemuCaps, + parse_flags, + driver->xmlopt)) < 0) + goto cleanup; +@@ -8585,7 +8588,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + + /* virDomainDefCompatibleDevice call is delayed until we know the + * device we're going to update. */ +- if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps, ++ if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps, priv->qemuCaps, + parse_flags, + driver->xmlopt)) < 0) + goto endjob; +@@ -8680,7 +8683,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver, + if (!vmdef) + goto cleanup; + +- if (qemuDomainDetachDeviceConfig(vmdef, dev, caps, ++ if (qemuDomainDetachDeviceConfig(vmdef, dev, caps, priv->qemuCaps, + parse_flags, + driver->xmlopt) < 0) + goto cleanup; +@@ -8766,7 +8769,7 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver, + if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0) + goto cleanup; + +- if (qemuDomainDetachDeviceConfig(vmdef, &dev, caps, ++ if (qemuDomainDetachDeviceConfig(vmdef, &dev, caps, priv->qemuCaps, + parse_flags, driver->xmlopt) < 0) + goto cleanup; + } +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 08e1d91fcc..307098cd63 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -5350,7 +5350,7 @@ qemuProcessInit(virQEMUDriverPtr driver, + if (vm->def->postParseFailed) { + VIR_DEBUG("re-running the post parse callback"); + +- if (virDomainDefPostParse(vm->def, caps, 0, driver->xmlopt, NULL) < 0) ++ if (virDomainDefPostParse(vm->def, caps, 0, driver->xmlopt, priv->qemuCaps) < 0) + goto cleanup; + } + +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDeviceDefPostParse.patch b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDeviceDefPostParse.patch new file mode 100644 index 0000000..3d2bc15 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDeviceDefPostParse.patch @@ -0,0 +1,419 @@ +From 9ca9c90ecfc021f735769307253319a730bc2565 Mon Sep 17 00:00:00 2001 +Message-Id: <9ca9c90ecfc021f735769307253319a730bc2565@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:36 +0200 +Subject: [PATCH] qemu: Pass correct qemuCaps to virDomainDeviceDefPostParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDeviceDefPostParse callback requires qemuCaps, we need +to make sure it gets the capabilities stored in the domain's private +data if the domain is running. Passing NULL may cause QEMU capabilities +probing to be triggered in case QEMU binary changed in the meantime. +When this happens while a running domain object is locked, QMP event +delivered to the domain before QEMU capabilities probing finishes will +deadlock the event loop. + +QEMU capabilities lookup (via domainPostParseDataAlloc callback) is +hidden inside virDomainDeviceDefPostParseOne with no way to pass +qemuCaps to virDomainDeviceDef* functions. This patch fixes all +remaining paths leading to virDomainDeviceDefPostParse. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit b449c270416468ec8b73670b49a9aff87c8902a2) + +Conflicts: + src/conf/domain_conf.c + src/conf/domain_conf.h + - context + + src/lxc/lxc_driver.c + - lxcDomainUpdateDeviceFlags is different upstream + + src/qemu/qemu_driver.c + - qemuDomainAttachDeviceLiveAndConfig is different upstream + + src/uml/uml_driver.c + - uml driver was removed upstream + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <26b6c56b3da907b14e201b23bec6164037151fb6.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 23 ++++++++++++++--------- + src/conf/domain_conf.h | 4 +++- + src/libxl/libxl_driver.c | 12 ++++++------ + src/lxc/lxc_driver.c | 12 ++++++------ + src/openvz/openvz_driver.c | 2 +- + src/phyp/phyp_driver.c | 2 +- + src/qemu/qemu_driver.c | 19 +++++++++++-------- + src/uml/uml_driver.c | 3 ++- + src/vbox/vbox_common.c | 4 ++-- + tests/qemuhotplugtest.c | 2 +- + 10 files changed, 47 insertions(+), 36 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 0fdf1742fd..637d971e21 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -4961,22 +4961,24 @@ virDomainDeviceDefPostParseOne(virDomainDeviceDefPtr dev, + const virDomainDef *def, + virCapsPtr caps, + unsigned int flags, +- virDomainXMLOptionPtr xmlopt) ++ virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque) + { +- void *parseOpaque = NULL; ++ void *data = NULL; + int ret; + +- if (xmlopt->config.domainPostParseDataAlloc) { ++ if (!parseOpaque && xmlopt->config.domainPostParseDataAlloc) { + if (xmlopt->config.domainPostParseDataAlloc(def, caps, flags, + xmlopt->config.priv, +- &parseOpaque) < 0) ++ &data) < 0) + return -1; ++ parseOpaque = data; + } + + ret = virDomainDeviceDefPostParse(dev, def, caps, flags, xmlopt, parseOpaque); + +- if (parseOpaque && xmlopt->config.domainPostParseDataFree) +- xmlopt->config.domainPostParseDataFree(parseOpaque); ++ if (data && xmlopt->config.domainPostParseDataFree) ++ xmlopt->config.domainPostParseDataFree(data); + + return ret; + } +@@ -16321,6 +16323,7 @@ virDomainDeviceDefParse(const char *xmlStr, + const virDomainDef *def, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags) + { + xmlDocPtr xml; +@@ -16482,7 +16485,8 @@ virDomainDeviceDefParse(const char *xmlStr, + } + + /* callback to fill driver specific device aspects */ +- if (virDomainDeviceDefPostParseOne(dev, def, caps, flags, xmlopt) < 0) ++ if (virDomainDeviceDefPostParseOne(dev, def, caps, flags, ++ xmlopt, parseOpaque) < 0) + goto error; + + /* validate the configuration */ +@@ -29593,7 +29597,8 @@ virDomainDeviceDefPtr + virDomainDeviceDefCopy(virDomainDeviceDefPtr src, + const virDomainDef *def, + virCapsPtr caps, +- virDomainXMLOptionPtr xmlopt) ++ virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque) + { + virDomainDeviceDefPtr ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; +@@ -29682,7 +29687,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, + goto cleanup; + + xmlStr = virBufferContentAndReset(&buf); +- ret = virDomainDeviceDefParse(xmlStr, def, caps, xmlopt, ++ ret = virDomainDeviceDefParse(xmlStr, def, caps, xmlopt, parseOpaque, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); + +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 9e4fed6d4e..0989368e7c 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2906,7 +2906,8 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def); + virDomainDeviceDefPtr virDomainDeviceDefCopy(virDomainDeviceDefPtr src, + const virDomainDef *def, + virCapsPtr caps, +- virDomainXMLOptionPtr xmlopt); ++ virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque); + int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, + int type); + virDomainDeviceInfoPtr virDomainDeviceGetInfo(virDomainDeviceDefPtr device); +@@ -3039,6 +3040,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr, + const virDomainDef *def, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ void *parseOpaque, + unsigned int flags); + virDomainDiskDefPtr virDomainDiskDefParse(const char *xmlStr, + const virDomainDef *def, +diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c +index be6b66ce7e..1eb63c5b64 100644 +--- a/src/libxl/libxl_driver.c ++++ b/src/libxl/libxl_driver.c +@@ -3955,7 +3955,7 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto endjob; + +@@ -3972,7 +3972,7 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + /* If dev exists it was created to modify the domain config. Free it. */ + virDomainDeviceDefFree(dev); + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto endjob; + +@@ -4044,7 +4044,7 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + goto endjob; +@@ -4062,7 +4062,7 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + /* If dev exists it was created to modify the domain config. Free it. */ + virDomainDeviceDefFree(dev); + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + goto endjob; +@@ -4132,7 +4132,7 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto cleanup; + +@@ -4151,7 +4151,7 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + /* If dev exists it was created to modify the domain config. Free it. */ + virDomainDeviceDefFree(dev); + if (!(dev = virDomainDeviceDefParse(xml, vm->def, +- cfg->caps, driver->xmlopt, ++ cfg->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto cleanup; + +diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c +index b182fa3759..5978183e7f 100644 +--- a/src/lxc/lxc_driver.c ++++ b/src/lxc/lxc_driver.c +@@ -4736,7 +4736,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, + goto endjob; + + dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE); + if (dev == NULL) + goto endjob; +@@ -4748,7 +4748,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, + * to CONFIG takes one instance. + */ + dev_copy = virDomainDeviceDefCopy(dev, vm->def, +- caps, driver->xmlopt); ++ caps, driver->xmlopt, NULL); + if (!dev_copy) + goto endjob; + } +@@ -4851,7 +4851,7 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom, + goto endjob; + + dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE); + if (dev == NULL) + goto endjob; +@@ -4863,7 +4863,7 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom, + * to CONFIG takes one instance. + */ + dev_copy = virDomainDeviceDefCopy(dev, vm->def, +- caps, driver->xmlopt); ++ caps, driver->xmlopt, NULL); + if (!dev_copy) + goto endjob; + } +@@ -4941,7 +4941,7 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom, + goto endjob; + + dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); + if (dev == NULL) +@@ -4954,7 +4954,7 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom, + * to CONFIG takes one instance. + */ + dev_copy = virDomainDeviceDefCopy(dev, vm->def, +- caps, driver->xmlopt); ++ caps, driver->xmlopt, NULL); + if (!dev_copy) + goto endjob; + } +diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c +index 14295dfda0..d6efb70209 100644 +--- a/src/openvz/openvz_driver.c ++++ b/src/openvz/openvz_driver.c +@@ -1972,7 +1972,7 @@ openvzDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + if (!(def = virDomainObjGetOneDef(vm, flags))) + goto cleanup; + +- dev = virDomainDeviceDefParse(xml, def, driver->caps, driver->xmlopt, ++ dev = virDomainDeviceDefParse(xml, def, driver->caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE); + if (!dev) + goto cleanup; +diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c +index 67ce7903ba..430472e724 100644 +--- a/src/phyp/phyp_driver.c ++++ b/src/phyp/phyp_driver.c +@@ -1721,7 +1721,7 @@ phypDomainAttachDevice(virDomainPtr domain, const char *xml) + + def->os.type = VIR_DOMAIN_OSTYPE_LINUX; + +- dev = virDomainDeviceDefParse(xml, def, phyp_driver->caps, NULL, ++ dev = virDomainDeviceDefParse(xml, def, phyp_driver->caps, NULL, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE); + if (!dev) + goto cleanup; +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 00213a5f80..8ecdcf3440 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -8405,7 +8405,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, + goto cleanup; + + dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ caps, driver->xmlopt, priv->qemuCaps, + parse_flags); + if (dev == NULL) + goto cleanup; +@@ -8419,7 +8419,8 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm, + * create a deep copy of device as adding + * to CONFIG takes one instance. + */ +- dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt); ++ dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt, ++ priv->qemuCaps); + if (!dev_copy) + goto cleanup; + } +@@ -8567,8 +8568,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + !(flags & VIR_DOMAIN_AFFECT_LIVE)) + parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE; + +- dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, caps, ++ driver->xmlopt, priv->qemuCaps, + parse_flags); + if (dev == NULL) + goto endjob; +@@ -8579,7 +8580,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, + * create a deep copy of device as adding + * to CONFIG takes one instance. + */ +- dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt); ++ dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, ++ driver->xmlopt, priv->qemuCaps); + if (!dev_copy) + goto endjob; + } +@@ -8665,8 +8667,8 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver, + !(flags & VIR_DOMAIN_AFFECT_LIVE)) + parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE; + +- dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, +- caps, driver->xmlopt, ++ dev = dev_copy = virDomainDeviceDefParse(xml, vm->def, caps, ++ driver->xmlopt, priv->qemuCaps, + parse_flags); + if (dev == NULL) + goto cleanup; +@@ -8677,7 +8679,8 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver, + * create a deep copy of device as adding + * to CONFIG takes one instance. + */ +- dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt); ++ dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, ++ driver->xmlopt, priv->qemuCaps); + if (!dev_copy) + goto cleanup; + } +diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c +index 796de53d43..175d6c9c2e 100644 +--- a/src/uml/uml_driver.c ++++ b/src/uml/uml_driver.c +@@ -2089,7 +2089,7 @@ static int umlDomainAttachDevice(virDomainPtr dom, const char *xml) + } + + dev = virDomainDeviceDefParse(xml, vm->def, driver->caps, driver->xmlopt, +- VIR_DOMAIN_DEF_PARSE_INACTIVE); ++ NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE); + + if (dev == NULL) + goto cleanup; +@@ -2202,6 +2202,7 @@ static int umlDomainDetachDevice(virDomainPtr dom, const char *xml) + } + + dev = virDomainDeviceDefParse(xml, vm->def, driver->caps, driver->xmlopt, ++ NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); + if (dev == NULL) +diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c +index 46d2b7afa3..eed7c83913 100644 +--- a/src/vbox/vbox_common.c ++++ b/src/vbox/vbox_common.c +@@ -4313,7 +4313,7 @@ static int vboxDomainAttachDeviceImpl(virDomainPtr dom, + + def->os.type = VIR_DOMAIN_OSTYPE_HVM; + +- dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, ++ dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE); + if (dev == NULL) + goto cleanup; +@@ -4432,7 +4432,7 @@ static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) + + def->os.type = VIR_DOMAIN_OSTYPE_HVM; + +- dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, ++ dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); + if (dev == NULL) +diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c +index 2dbf768e16..b202ade286 100644 +--- a/tests/qemuhotplugtest.c ++++ b/tests/qemuhotplugtest.c +@@ -272,7 +272,7 @@ testQemuHotplug(const void *data) + device_parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; + + if (!(dev = virDomainDeviceDefParse(device_xml, vm->def, +- caps, driver.xmlopt, ++ caps, driver.xmlopt, NULL, + device_parse_flags))) + goto cleanup; + +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefCopy.patch b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefCopy.patch new file mode 100644 index 0000000..0995015 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefCopy.patch @@ -0,0 +1,201 @@ +From 7a3e5357cdd44f372dc8020395bdfd818d3453ed Mon Sep 17 00:00:00 2001 +Message-Id: <7a3e5357cdd44f372dc8020395bdfd818d3453ed@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:27 +0200 +Subject: [PATCH] qemu: Pass qemuCaps to qemuDomainDefCopy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to qemuDomainDefCopy. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit a42f889591c16235e0fe349e509af896fa1ea5ff) + +Conflicts: + src/qemu/qemu_driver.c + - context + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <6ecee413894eadadaf37884be7dd4136ad2de403.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_domain.c | 16 ++++++++++------ + src/qemu/qemu_domain.h | 2 ++ + src/qemu/qemu_driver.c | 9 +++++---- + src/qemu/qemu_migration.c | 4 ++-- + 4 files changed, 19 insertions(+), 12 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index 81699110fc..bf6013d42a 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -7203,6 +7203,7 @@ qemuDomainObjExitRemote(virDomainObjPtr obj, + + static virDomainDefPtr + qemuDomainDefFromXML(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + const char *xml) + { + virCapsPtr caps; +@@ -7211,7 +7212,7 @@ qemuDomainDefFromXML(virQEMUDriverPtr driver, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + return NULL; + +- def = virDomainDefParseString(xml, caps, driver->xmlopt, NULL, ++ def = virDomainDefParseString(xml, caps, driver->xmlopt, qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); + +@@ -7222,6 +7223,7 @@ qemuDomainDefFromXML(virQEMUDriverPtr driver, + + virDomainDefPtr + qemuDomainDefCopy(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr src, + unsigned int flags) + { +@@ -7231,7 +7233,7 @@ qemuDomainDefCopy(virQEMUDriverPtr driver, + if (!(xml = qemuDomainDefFormatXML(driver, src, flags))) + return NULL; + +- ret = qemuDomainDefFromXML(driver, xml); ++ ret = qemuDomainDefFromXML(driver, qemuCaps, xml); + + VIR_FREE(xml); + return ret; +@@ -9052,6 +9054,7 @@ qemuDomainMigratableDefCheckABIStability(virQEMUDriverPtr driver, + + bool + qemuDomainDefCheckABIStability(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr src, + virDomainDefPtr dst) + { +@@ -9059,8 +9062,8 @@ qemuDomainDefCheckABIStability(virQEMUDriverPtr driver, + virDomainDefPtr migratableDefDst = NULL; + bool ret = false; + +- if (!(migratableDefSrc = qemuDomainDefCopy(driver, src, COPY_FLAGS)) || +- !(migratableDefDst = qemuDomainDefCopy(driver, dst, COPY_FLAGS))) ++ if (!(migratableDefSrc = qemuDomainDefCopy(driver, qemuCaps, src, COPY_FLAGS)) || ++ !(migratableDefDst = qemuDomainDefCopy(driver, qemuCaps, dst, COPY_FLAGS))) + goto cleanup; + + ret = qemuDomainMigratableDefCheckABIStability(driver, +@@ -9079,14 +9082,15 @@ qemuDomainCheckABIStability(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDefPtr dst) + { ++ qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr migratableSrc = NULL; + virDomainDefPtr migratableDst = NULL; + char *xml = NULL; + bool ret = false; + + if (!(xml = qemuDomainFormatXML(driver, vm, COPY_FLAGS)) || +- !(migratableSrc = qemuDomainDefFromXML(driver, xml)) || +- !(migratableDst = qemuDomainDefCopy(driver, dst, COPY_FLAGS))) ++ !(migratableSrc = qemuDomainDefFromXML(driver, priv->qemuCaps, xml)) || ++ !(migratableDst = qemuDomainDefCopy(driver, priv->qemuCaps, dst, COPY_FLAGS))) + goto cleanup; + + ret = qemuDomainMigratableDefCheckABIStability(driver, +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index cc406e3ca0..29283105cb 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -594,6 +594,7 @@ int qemuDomainObjExitRemote(virDomainObjPtr obj, + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + + virDomainDefPtr qemuDomainDefCopy(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr src, + unsigned int flags); + +@@ -769,6 +770,7 @@ int qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver, + int asyncJob); + + bool qemuDomainDefCheckABIStability(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr src, + virDomainDefPtr dst); + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 25818f5d8c..a486c66a5f 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -6325,7 +6325,7 @@ qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto cleanup; + +- if (!(newdef_migr = qemuDomainDefCopy(driver, ++ if (!(newdef_migr = qemuDomainDefCopy(driver, NULL, + newdef, + QEMU_DOMAIN_FORMAT_LIVE_FLAGS | + VIR_DOMAIN_XML_MIGRATABLE))) +@@ -16052,7 +16052,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + switch ((virDomainState) snap->def->state) { + case VIR_DOMAIN_RUNNING: + case VIR_DOMAIN_PAUSED: +- ++ priv = vm->privateData; + start_flags |= VIR_QEMU_PROCESS_START_PAUSED; + + /* Transitions 2, 3, 5, 6, 8, 9 */ +@@ -16079,7 +16079,9 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + if (!(config->cpu = virCPUDefCopy(cookie->cpu))) + goto endjob; + +- compatible = qemuDomainDefCheckABIStability(driver, vm->def, ++ compatible = qemuDomainDefCheckABIStability(driver, ++ priv->qemuCaps, ++ vm->def, + config); + } else { + compatible = qemuDomainCheckABIStability(driver, vm, config); +@@ -16123,7 +16125,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + } + } + +- priv = vm->privateData; + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { + /* Transitions 5, 6 */ + if (qemuProcessStopCPUs(driver, vm, +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 67940330aa..4af105b997 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2378,7 +2378,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, + if (!newdef) + goto cleanup; + +- if (!qemuDomainDefCheckABIStability(driver, *def, newdef)) { ++ if (!qemuDomainDefCheckABIStability(driver, NULL, *def, newdef)) { + virDomainDefFree(newdef); + goto cleanup; + } +@@ -3417,7 +3417,7 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver, + goto error; + } else { + virDomainDefPtr def = vm->newDef ? vm->newDef : vm->def; +- if (!(persistDef = qemuDomainDefCopy(driver, def, ++ if (!(persistDef = qemuDomainDefCopy(driver, priv->qemuCaps, def, + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_MIGRATABLE))) + goto error; +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefFormatBufInternal.patch b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefFormatBufInternal.patch new file mode 100644 index 0000000..f193446 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefFormatBufInternal.patch @@ -0,0 +1,430 @@ +From 0379563f7961e019ceef28ed28e56bb24f78d778 Mon Sep 17 00:00:00 2001 +Message-Id: <0379563f7961e019ceef28ed28e56bb24f78d778@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:28 +0200 +Subject: [PATCH] qemu: Pass qemuCaps to qemuDomainDefFormatBufInternal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to qemuDomainDefFormatBufInternal. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 900c5952499fb233a9c0d2e6d0a5fde84a99cf72) + +Conflicts: + src/qemu/qemu_driver.c + - no checkpoint APIs + - no VIR_AUTOUNREF + - ProcessAttach and XMLFromNative APIs were removed upstream + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_domain.c | 37 ++++++++++++++++++++------------ + src/qemu/qemu_domain.h | 3 +++ + src/qemu/qemu_driver.c | 22 ++++++++++++------- + src/qemu/qemu_migration.c | 6 +++--- + src/qemu/qemu_migration_cookie.c | 9 ++++++-- + src/qemu/qemu_process.c | 11 +++++----- + 6 files changed, 56 insertions(+), 32 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index bf6013d42a..249ec4d259 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -7230,7 +7230,7 @@ qemuDomainDefCopy(virQEMUDriverPtr driver, + virDomainDefPtr ret = NULL; + char *xml; + +- if (!(xml = qemuDomainDefFormatXML(driver, src, flags))) ++ if (!(xml = qemuDomainDefFormatXML(driver, qemuCaps, src, flags))) + return NULL; + + ret = qemuDomainDefFromXML(driver, qemuCaps, xml); +@@ -7242,6 +7242,7 @@ qemuDomainDefCopy(virQEMUDriverPtr driver, + + static int + qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + virCPUDefPtr origCPU, + unsigned int flags, +@@ -7250,7 +7251,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, + int ret = -1; + virDomainDefPtr copy = NULL; + virCapsPtr caps = NULL; +- virQEMUCapsPtr qemuCaps = NULL; ++ virQEMUCapsPtr qCaps = NULL; + + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto cleanup; +@@ -7258,7 +7259,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, + if (!(flags & (VIR_DOMAIN_XML_UPDATE_CPU | VIR_DOMAIN_XML_MIGRATABLE))) + goto format; + +- if (!(copy = virDomainDefCopy(def, caps, driver->xmlopt, NULL, ++ if (!(copy = virDomainDefCopy(def, caps, driver->xmlopt, qemuCaps, + flags & VIR_DOMAIN_XML_MIGRATABLE))) + goto cleanup; + +@@ -7269,13 +7270,17 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, + def->cpu && + (def->cpu->mode != VIR_CPU_MODE_CUSTOM || + def->cpu->model)) { +- if (!(qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, +- def->emulator, +- def->os.machine))) +- goto cleanup; ++ if (qemuCaps) { ++ qCaps = virObjectRef(qemuCaps); ++ } else { ++ if (!(qCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, ++ def->emulator, ++ def->os.machine))) ++ goto cleanup; ++ } + + if (virCPUUpdate(def->os.arch, def->cpu, +- virQEMUCapsGetHostModel(qemuCaps, def->virtType, ++ virQEMUCapsGetHostModel(qCaps, def->virtType, + VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) < 0) + goto cleanup; + } +@@ -7424,30 +7429,32 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver, + cleanup: + virDomainDefFree(copy); + virObjectUnref(caps); +- virObjectUnref(qemuCaps); ++ virObjectUnref(qCaps); + return ret; + } + + + int + qemuDomainDefFormatBuf(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + unsigned int flags, + virBufferPtr buf) + { +- return qemuDomainDefFormatBufInternal(driver, def, NULL, flags, buf); ++ return qemuDomainDefFormatBufInternal(driver, qemuCaps, def, NULL, flags, buf); + } + + + static char * + qemuDomainDefFormatXMLInternal(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + virCPUDefPtr origCPU, + unsigned int flags) + { + virBuffer buf = VIR_BUFFER_INITIALIZER; + +- if (qemuDomainDefFormatBufInternal(driver, def, origCPU, flags, &buf) < 0) ++ if (qemuDomainDefFormatBufInternal(driver, qemuCaps, def, origCPU, flags, &buf) < 0) + return NULL; + + return virBufferContentAndReset(&buf); +@@ -7456,10 +7463,11 @@ qemuDomainDefFormatXMLInternal(virQEMUDriverPtr driver, + + char * + qemuDomainDefFormatXML(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + unsigned int flags) + { +- return qemuDomainDefFormatXMLInternal(driver, def, NULL, flags); ++ return qemuDomainDefFormatXMLInternal(driver, qemuCaps, def, NULL, flags); + } + + +@@ -7478,11 +7486,12 @@ char *qemuDomainFormatXML(virQEMUDriverPtr driver, + origCPU = priv->origCPU; + } + +- return qemuDomainDefFormatXMLInternal(driver, def, origCPU, flags); ++ return qemuDomainDefFormatXMLInternal(driver, priv->qemuCaps, def, origCPU, flags); + } + + char * + qemuDomainDefFormatLive(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + virCPUDefPtr origCPU, + bool inactive, +@@ -7495,7 +7504,7 @@ qemuDomainDefFormatLive(virQEMUDriverPtr driver, + if (compatible) + flags |= VIR_DOMAIN_XML_MIGRATABLE; + +- return qemuDomainDefFormatXMLInternal(driver, def, origCPU, flags); ++ return qemuDomainDefFormatXMLInternal(driver, qemuCaps, def, origCPU, flags); + } + + +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index 29283105cb..9546216f30 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -599,11 +599,13 @@ virDomainDefPtr qemuDomainDefCopy(virQEMUDriverPtr driver, + unsigned int flags); + + int qemuDomainDefFormatBuf(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr vm, + unsigned int flags, + virBuffer *buf); + + char *qemuDomainDefFormatXML(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr vm, + unsigned int flags); + +@@ -612,6 +614,7 @@ char *qemuDomainFormatXML(virQEMUDriverPtr driver, + unsigned int flags); + + char *qemuDomainDefFormatLive(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virDomainDefPtr def, + virCPUDefPtr origCPU, + bool inactive, +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index a486c66a5f..7d87215904 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -3316,9 +3316,10 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, + virDomainDefFree(def); + goto endjob; + } +- xml = qemuDomainDefFormatLive(driver, def, NULL, true, true); ++ xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, def, NULL, true, true); + } else { +- xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, true, true); ++ xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, vm->def, ++ priv->origCPU, true, true); + } + if (!xml) { + virReportError(VIR_ERR_OPERATION_FAILED, +@@ -6787,7 +6788,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, + if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) + goto cleanup; + +- ret = qemuDomainDefFormatXML(driver, def, flags); ++ ret = qemuDomainDefFormatXML(driver, NULL, def, flags); + + cleanup: + virQEMUSaveDataFree(data); +@@ -6840,7 +6841,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, + + VIR_FREE(data->xml); + +- if (!(data->xml = qemuDomainDefFormatXML(driver, newdef, ++ if (!(data->xml = qemuDomainDefFormatXML(driver, NULL, newdef, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_MIGRATABLE))) +@@ -6879,6 +6880,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) + virDomainDefPtr def = NULL; + int fd = -1; + virQEMUSaveDataPtr data = NULL; ++ qemuDomainObjPrivatePtr priv; + + /* We only take subset of virDomainDefFormat flags. */ + virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL); +@@ -6886,6 +6888,8 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) + if (!(vm = qemuDomObjFromDomain(dom))) + return ret; + ++ priv = vm->privateData; ++ + if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + +@@ -6902,7 +6906,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) + false, NULL, false, false)) < 0) + goto cleanup; + +- ret = qemuDomainDefFormatXML(driver, def, flags); ++ ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); + + cleanup: + virQEMUSaveDataFree(data); +@@ -7097,7 +7101,7 @@ static char *qemuConnectDomainXMLFromNative(virConnectPtr conn, + if (!def->name && VIR_STRDUP(def->name, "unnamed") < 0) + goto cleanup; + +- xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE); ++ xml = qemuDomainDefFormatXML(driver, NULL, def, VIR_DOMAIN_XML_INACTIVE); + + cleanup: + virDomainDefFree(def); +@@ -15151,7 +15155,8 @@ qemuDomainSnapshotCreateActiveExternal(virQEMUDriverPtr driver, + "snapshot", false)) < 0) + goto cleanup; + +- if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, ++ if (!(xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, ++ vm->def, priv->origCPU, + true, true)) || + !(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm))) + goto cleanup; +@@ -15395,7 +15400,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, + } else { + /* Easiest way to clone inactive portion of vm->def is via + * conversion in and back out of xml. */ +- if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, ++ if (!(xml = qemuDomainDefFormatLive(driver, priv->qemuCaps, ++ vm->def, priv->origCPU, + true, true)) || + !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE | +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 4af105b997..111038b971 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2081,9 +2081,9 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver, + if (!qemuDomainCheckABIStability(driver, vm, def)) + goto cleanup; + +- rv = qemuDomainDefFormatLive(driver, def, NULL, false, true); ++ rv = qemuDomainDefFormatLive(driver, priv->qemuCaps, def, NULL, false, true); + } else { +- rv = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, ++ rv = qemuDomainDefFormatLive(driver, priv->qemuCaps, vm->def, priv->origCPU, + false, true); + } + +@@ -2352,7 +2352,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, + char *xml; + int hookret; + +- if (!(xml = qemuDomainDefFormatXML(driver, *def, ++ if (!(xml = qemuDomainDefFormatXML(driver, NULL, *def, + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_MIGRATABLE))) + goto cleanup; +diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c +index 60df449d53..901b1ae9ac 100644 +--- a/src/qemu/qemu_migration_cookie.c ++++ b/src/qemu/qemu_migration_cookie.c +@@ -777,6 +777,7 @@ qemuMigrationCookieCapsXMLFormat(virBufferPtr buf, + + static int + qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + virBufferPtr buf, + qemuMigrationCookiePtr mig) + { +@@ -818,6 +819,7 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, + if ((mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && + mig->persistent) { + if (qemuDomainDefFormatBuf(driver, ++ qemuCaps, + mig->persistent, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE | +@@ -869,11 +871,12 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, + + static char * + qemuMigrationCookieXMLFormatStr(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + qemuMigrationCookiePtr mig) + { + virBuffer buf = VIR_BUFFER_INITIALIZER; + +- if (qemuMigrationCookieXMLFormat(driver, &buf, mig) < 0) { ++ if (qemuMigrationCookieXMLFormat(driver, qemuCaps, &buf, mig) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } +@@ -1416,6 +1419,8 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, + int *cookieoutlen, + unsigned int flags) + { ++ qemuDomainObjPrivatePtr priv = dom->privateData; ++ + if (!cookieout || !cookieoutlen) + return 0; + +@@ -1459,7 +1464,7 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, + qemuMigrationCookieAddCaps(mig, dom, party) < 0) + return -1; + +- if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig))) ++ if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, priv->qemuCaps, mig))) + return -1; + + *cookieoutlen = strlen(*cookieout) + 1; +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 9e6e6528e2..34686b4d92 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -4434,13 +4434,14 @@ qemuProcessStartHook(virQEMUDriverPtr driver, + virHookQemuOpType op, + virHookSubopType subop) + { ++ qemuDomainObjPrivatePtr priv = vm->privateData; + char *xml; + int ret; + + if (!virHookPresent(VIR_HOOK_DRIVER_QEMU)) + return 0; + +- if (!(xml = qemuDomainDefFormatXML(driver, vm->def, 0))) ++ if (!(xml = qemuDomainDefFormatXML(driver, priv->qemuCaps, vm->def, 0))) + return -1; + + ret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name, op, subop, +@@ -7091,7 +7092,7 @@ void qemuProcessStop(virQEMUDriverPtr driver, + + /* now that we know it's stopped call the hook if present */ + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { +- char *xml = qemuDomainDefFormatXML(driver, vm->def, 0); ++ char *xml = qemuDomainDefFormatXML(driver, NULL, vm->def, 0); + + /* we can't stop the operation even if the script raised an error */ + ignore_value(virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name, +@@ -7249,7 +7250,7 @@ void qemuProcessStop(virQEMUDriverPtr driver, + + /* The "release" hook cleans up additional resources */ + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { +- char *xml = qemuDomainDefFormatXML(driver, vm->def, 0); ++ char *xml = qemuDomainDefFormatXML(driver, NULL, vm->def, 0); + + /* we can't stop the operation even if the script raised an error */ + virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name, +@@ -7473,7 +7474,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, + + /* Run an hook to allow admins to do some magic */ + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { +- char *xml = qemuDomainDefFormatXML(driver, vm->def, 0); ++ char *xml = qemuDomainDefFormatXML(driver, priv->qemuCaps, vm->def, 0); + int hookret; + + hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name, +@@ -7934,7 +7935,7 @@ qemuProcessReconnect(void *opaque) + + /* Run an hook to allow admins to do some magic */ + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { +- char *xml = qemuDomainDefFormatXML(driver, obj->def, 0); ++ char *xml = qemuDomainDefFormatXML(driver, priv->qemuCaps, obj->def, 0); + int hookret; + + hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, obj->def->name, +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainSaveImageOpen.patch b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainSaveImageOpen.patch new file mode 100644 index 0000000..2b3871e --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuDomainSaveImageOpen.patch @@ -0,0 +1,110 @@ +From b0e155481dd03971fe3d24b9abbe3cdf0e2373c4 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:29 +0200 +Subject: [PATCH] qemu: Pass qemuCaps to qemuDomainSaveImageOpen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to qemuDomainSaveImageOpen. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit fd60aefec7f49d1053efdd5119db494bb474aeec) + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <6206f14c127037e0822fb6c1e04e8f2d8e6069ce.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_driver.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 7d87215904..04915798ab 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -6368,6 +6368,7 @@ qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver, + /** + * qemuDomainSaveImageOpen: + * @driver: qemu driver data ++ * @qemuCaps: pointer to qemuCaps if the domain is running or NULL + * @path: path of the save image + * @ret_def: returns domain definition created from the XML stored in the image + * @ret_data: returns structure filled with data from the image header +@@ -6382,6 +6383,7 @@ qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver, + */ + static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + qemuDomainSaveImageOpen(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + const char *path, + virDomainDefPtr *ret_def, + virQEMUSaveDataPtr *ret_data, +@@ -6506,7 +6508,7 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver, + } + + /* Create a domain from this XML */ +- if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL, ++ if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + goto error; +@@ -6681,7 +6683,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, + + virNWFilterReadLockFilterUpdates(); + +- fd = qemuDomainSaveImageOpen(driver, path, &def, &data, ++ fd = qemuDomainSaveImageOpen(driver, NULL, path, &def, &data, + (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, + &wrapperFd, false, false); + if (fd < 0) +@@ -6779,7 +6781,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, + /* We only take subset of virDomainDefFormat flags. */ + virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL); + +- fd = qemuDomainSaveImageOpen(driver, path, &def, &data, ++ fd = qemuDomainSaveImageOpen(driver, NULL, path, &def, &data, + false, NULL, false, false); + + if (fd < 0) +@@ -6817,7 +6819,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, + else if (flags & VIR_DOMAIN_SAVE_PAUSED) + state = 0; + +- fd = qemuDomainSaveImageOpen(driver, path, &def, &data, ++ fd = qemuDomainSaveImageOpen(driver, NULL, path, &def, &data, + false, NULL, true, false); + + if (fd < 0) +@@ -6902,7 +6904,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) + goto cleanup; + } + +- if ((fd = qemuDomainSaveImageOpen(driver, path, &def, &data, ++ if ((fd = qemuDomainSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, + false, NULL, false, false)) < 0) + goto cleanup; + +@@ -6969,7 +6971,7 @@ qemuDomainObjRestore(virConnectPtr conn, + virQEMUSaveDataPtr data = NULL; + virFileWrapperFdPtr wrapperFd = NULL; + +- fd = qemuDomainSaveImageOpen(driver, path, &def, &data, ++ fd = qemuDomainSaveImageOpen(driver, NULL, path, &def, &data, + bypass_cache, &wrapperFd, false, true); + if (fd < 0) { + if (fd == -3) +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationAnyPrepareDef.patch b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationAnyPrepareDef.patch new file mode 100644 index 0000000..088d279 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationAnyPrepareDef.patch @@ -0,0 +1,141 @@ +From 54ca487f3777497fb419884d187bf2be00ed60f1 Mon Sep 17 00:00:00 2001 +Message-Id: <54ca487f3777497fb419884d187bf2be00ed60f1@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:30 +0200 +Subject: [PATCH] qemu: Pass qemuCaps to qemuMigrationAnyPrepareDef +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to qemuMigrationAnyPrepareDef. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit b900f7387fca1cf3567935c81136579d6bee95ca) + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: <9c8ee8580063e52b001b969a2fbb1f1cc3ebfc37.1565959866.git.jdenemar@redhat.com> +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_driver.c | 12 ++++++------ + src/qemu/qemu_migration.c | 8 ++++++-- + src/qemu/qemu_migration.h | 1 + + 3 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 04915798ab..590596a421 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -12184,7 +12184,7 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, + goto cleanup; + } + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0) +@@ -12245,7 +12245,7 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, + goto cleanup; + } + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0) +@@ -12487,7 +12487,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, + QEMU_MIGRATION_DESTINATION))) + goto cleanup; + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0) +@@ -12574,7 +12574,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn, + goto cleanup; + } + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0) +@@ -12628,7 +12628,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, + QEMU_MIGRATION_DESTINATION))) + goto cleanup; + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0) +@@ -12687,7 +12687,7 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn, + QEMU_MIGRATION_DESTINATION))) + goto cleanup; + +- if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname))) ++ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) + goto cleanup; + + if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0) +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 111038b971..f5d77d2508 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2852,6 +2852,7 @@ qemuMigrationDstPrepareDirect(virQEMUDriverPtr driver, + + virDomainDefPtr + qemuMigrationAnyPrepareDef(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + const char *dom_xml, + const char *dname, + char **origname) +@@ -2869,7 +2870,8 @@ qemuMigrationAnyPrepareDef(virQEMUDriverPtr driver, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + return NULL; + +- if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, NULL, ++ if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, ++ qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + goto cleanup; +@@ -3412,7 +3414,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver, + + if (flags & VIR_MIGRATE_PERSIST_DEST) { + if (persist_xml) { +- if (!(persistDef = qemuMigrationAnyPrepareDef(driver, persist_xml, ++ if (!(persistDef = qemuMigrationAnyPrepareDef(driver, ++ priv->qemuCaps, ++ persist_xml, + NULL, NULL))) + goto error; + } else { +diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h +index e12b6972db..b9feffaf93 100644 +--- a/src/qemu/qemu_migration.h ++++ b/src/qemu/qemu_migration.h +@@ -115,6 +115,7 @@ qemuMigrationSrcBegin(virConnectPtr conn, + + virDomainDefPtr + qemuMigrationAnyPrepareDef(virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + const char *dom_xml, + const char *dname, + char **origname); +-- +2.22.1 + diff --git a/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationCookieXMLParse.patch b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationCookieXMLParse.patch new file mode 100644 index 0000000..d50d577 --- /dev/null +++ b/SOURCES/libvirt-qemu-Pass-qemuCaps-to-qemuMigrationCookieXMLParse.patch @@ -0,0 +1,82 @@ +From 2178a6fc22688ff6c6464593823f11ead8cbe981 Mon Sep 17 00:00:00 2001 +Message-Id: <2178a6fc22688ff6c6464593823f11ead8cbe981@dist-git> +From: Jiri Denemark +Date: Fri, 16 Aug 2019 14:52:32 +0200 +Subject: [PATCH] qemu: Pass qemuCaps to qemuMigrationCookieXMLParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemuDomainDefPostParse callback requires qemuCaps, we need to make +sure it gets the capabilities stored in the domain's private data if the +domain is running. Passing NULL may cause QEMU capabilities probing to +be triggered in case QEMU binary changed in the meantime. When this +happens while a running domain object is locked, QMP event delivered to +the domain before QEMU capabilities probing finishes will deadlock the +event loop. + +This patch fixes all paths leading to qemuMigrationCookieXMLParse. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit bf15b145ec473c0ca5bfe8aee2bf0eb1691b6f1c) + +https://bugzilla.redhat.com/show_bug.cgi?id=1731783 +https://bugzilla.redhat.com/show_bug.cgi?id=1742023 + +Signed-off-by: Jiri Denemark +Message-Id: +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_migration_cookie.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c +index 901b1ae9ac..b9933b9e04 100644 +--- a/src/qemu/qemu_migration_cookie.c ++++ b/src/qemu/qemu_migration_cookie.c +@@ -1194,6 +1194,7 @@ qemuMigrationCookieCapsXMLParse(xmlXPathContextPtr ctxt) + static int + qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + xmlDocPtr doc, + xmlXPathContextPtr ctxt, + unsigned int flags) +@@ -1335,7 +1336,7 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + goto error; + } + mig->persistent = virDomainDefParseNode(doc, nodes[0], +- caps, driver->xmlopt, NULL, ++ caps, driver->xmlopt, qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_ABI_UPDATE_MIGRATION | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); +@@ -1388,6 +1389,7 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + static int + qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, + virQEMUDriverPtr driver, ++ virQEMUCapsPtr qemuCaps, + const char *xml, + unsigned int flags) + { +@@ -1400,7 +1402,7 @@ qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, + if (!(doc = virXMLParseStringCtxt(xml, _("(qemu_migration_cookie)"), &ctxt))) + goto cleanup; + +- ret = qemuMigrationCookieXMLParse(mig, driver, doc, ctxt, flags); ++ ret = qemuMigrationCookieXMLParse(mig, driver, qemuCaps, doc, ctxt, flags); + + cleanup: + xmlXPathFreeContext(ctxt); +@@ -1501,6 +1503,7 @@ qemuMigrationEatCookie(virQEMUDriverPtr driver, + if (cookiein && cookieinlen && + qemuMigrationCookieXMLParseStr(mig, + driver, ++ priv->qemuCaps, + cookiein, + flags) < 0) + goto error; +-- +2.22.1 + diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec index f4b1c12..9c264b5 100644 --- a/SPECS/libvirt.spec +++ b/SPECS/libvirt.spec @@ -253,7 +253,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 4.5.0 -Release: 23%{?dist}%{?extra_release} +Release: 23%{?dist}.1%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -579,6 +579,17 @@ Patch313: libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connect Patch314: libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch Patch315: libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch Patch316: libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch +Patch317: libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefCopy.patch +Patch318: libvirt-qemu-Pass-qemuCaps-to-qemuDomainDefFormatBufInternal.patch +Patch319: libvirt-qemu-Pass-qemuCaps-to-qemuDomainSaveImageOpen.patch +Patch320: libvirt-qemu-Pass-qemuCaps-to-qemuMigrationAnyPrepareDef.patch +Patch321: libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseString.patch +Patch322: libvirt-qemu-Pass-qemuCaps-to-qemuMigrationCookieXMLParse.patch +Patch323: libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefCopy.patch +Patch324: libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefPostParse.patch +Patch325: libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDefParseNode.patch +Patch326: libvirt-qemu-Pass-correct-qemuCaps-to-virDomainDeviceDefPostParse.patch +Patch327: libvirt-qemu-Fix-crash-on-incoming-migration.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2480,6 +2491,19 @@ exit 0 %changelog +* Fri Aug 16 2019 Jiri Denemark - 4.5.0-23.el7_7.1 +- qemu: Pass qemuCaps to qemuDomainDefCopy (rhbz#1742023) +- qemu: Pass qemuCaps to qemuDomainDefFormatBufInternal (rhbz#1742023) +- qemu: Pass qemuCaps to qemuDomainSaveImageOpen (rhbz#1742023) +- qemu: Pass qemuCaps to qemuMigrationAnyPrepareDef (rhbz#1742023) +- qemu: Pass correct qemuCaps to virDomainDefParseString (rhbz#1742023) +- qemu: Pass qemuCaps to qemuMigrationCookieXMLParse (rhbz#1742023) +- qemu: Pass correct qemuCaps to virDomainDefCopy (rhbz#1742023) +- qemu: Pass correct qemuCaps to virDomainDefPostParse (rhbz#1742023) +- qemu: Pass correct qemuCaps to virDomainDefParseNode (rhbz#1742023) +- qemu: Pass correct qemuCaps to virDomainDeviceDefPostParse (rhbz#1742023) +- qemu: Fix crash on incoming migration (rhbz#1742023) + * Thu Jun 20 2019 Jiri Denemark - 4.5.0-23 - api: disallow virDomainSaveImageGetXMLDesc on read-only connections (CVE-2019-10161) - api: disallow virDomainManagedSaveDefineXML on read-only connections (CVE-2019-10166)