[Pkg-libvirt-maintainers] Bug#1121534: trixie-pu: package libvirt/11.3.0-3+deb13u2

Andrea Bolognani eof at kiyuko.org
Thu Nov 27 22:47:57 GMT 2025


Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: libvirt at packages.debian.org
Control: affects -1 + src:libvirt
User: release.debian.org at packages.debian.org
Usertags: pu

Please approve the attached diff as a stable update to trixie.


[ Reason ]

Various fixes for libvirt in trixie, including addressing 2 CVEs.

[ Tests ]

I have manually verified 2 out of the 3 fixes. For the remaining one,
I have inspected the changes and found them to be reasonable. In all
cases the changes come directly from upstream via clean cherry-picks,
so I have very high confidence that they are correct.

[ Risks ]

Very little risk given the targeted nature of the fixes and their
origin. The libvirt project has an excellent track record when it
comes to preserving backwards compatibility and avoiding regressions.

[ Checklist ]

  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in stable
  [ ] the issue is verified as fixed in unstable

I have not backported the fixes to unstable because a new release of
libvirt (containing all these changes) is coming out next Monday and
I will update the package in unstable shortly afterwards, so doing
that at this point would be just a waste of everyone's time. If
getting the approval will take a few days, there's a high chance that
they will indeed hit unstable beforehand, in which case I will update
the bug report.

[ Changes ]

See the changelog.

-- 
Andrea Bolognani <eof at kiyuko.org>
Resistance is futile, you will be garbage collected.
-------------- next part --------------
diff -Nru libvirt-11.3.0/debian/changelog libvirt-11.3.0/debian/changelog
--- libvirt-11.3.0/debian/changelog	2025-11-02 16:54:31.000000000 +0100
+++ libvirt-11.3.0/debian/changelog	2025-11-25 01:07:00.000000000 +0100
@@ -1,3 +1,31 @@
+libvirt (11.3.0-3+deb13u2) trixie; urgency=medium
+
+  * [c5ef2ce] patches: Add backports
+    - backport/conf-Add-virDomainDefIDsParseString[...]
+    - backport/bhyve-Check-ACLs-before-parsing-[...]
+    - backport/libxl-Check-ACLs-before-parsing-[...]
+    - backport/lxc-Check-ACLs-before-parsing-[...]
+    - backport/vz-Check-ACLs-before-parsing-[...]
+    - backport/ch-Check-ACLs-before-parsing-[...]
+    - backport/qemu-Check-ACLs-before-parsing-[...]
+      - Perform ACL checks earlier, preventing malicious users
+        from potentially being able to crash the daemon
+      - CVE-2025-12748
+      - Closes: #1120584
+  * [9c44722] patches: Add backports
+    - backport/qemu-snapshot-Set-umask-for-qemu-img-[...]
+      - Ensure that newly-created snapshots are not world-readable
+      - CVE-2025-13193
+      - Closes: #1120119
+  * [74ba3ed] patches: Add backports
+    - backport/qemuxmlconftest-Improve-coverage-of-disk-[...]
+    - backport/qemu[...]-Setup-detect_zeroes-[...]
+      - Apply the detect_zeroes settings across all layers of the
+        backing chain instead of just the topmost one
+      - Closes: #1121280
+
+ -- Andrea Bolognani <eof at kiyuko.org>  Tue, 25 Nov 2025 01:07:00 +0100
+
 libvirt (11.3.0-3+deb13u1) trixie; urgency=medium
 
   * [6a549fc] patches: Add backports
diff -Nru libvirt-11.3.0/debian/patches/backport/bhyve-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/bhyve-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/bhyve-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/bhyve-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,74 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 15:31:12 +0100
+Subject: bhyve: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit b45f10bc0a2f30ccdbf2cb55da2e4f85b3ebfb23)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/b45f10bc0a2f30ccdbf2cb55da2e4f85b3ebfb23
+---
+ src/bhyve/bhyve_driver.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
+index 6843469..296837b 100644
+--- a/src/bhyve/bhyve_driver.c
++++ b/src/bhyve/bhyve_driver.c
+@@ -481,6 +481,15 @@ bhyveDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag
+     if (!caps)
+         return NULL;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, provconn->xmlopt, parse_flags)))
++        return NULL;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
++        return NULL;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
+     if ((def = virDomainDefParseString(xml, privconn->xmlopt,
+                                        NULL, parse_flags)) == NULL)
+         goto cleanup;
+@@ -488,9 +497,6 @@ bhyveDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag
+     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (bhyveDomainAssignAddresses(def, NULL) < 0)
+         goto cleanup;
+ 
+@@ -854,11 +860,17 @@ bhyveDomainCreateXML(virConnectPtr conn,
+     if (flags & VIR_DOMAIN_START_AUTODESTROY)
+         start_flags |= VIR_BHYVE_PROCESS_START_AUTODESTROY;
+ 
+-    if ((def = virDomainDefParseString(xml, privconn->xmlopt,
+-                                       NULL, parse_flags)) == NULL)
+-        goto cleanup;
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, provconn->xmlopt, parse_flags)))
++        return NULL;
+ 
+     if (virDomainCreateXMLEnsureACL(conn, def) < 0)
++        return NULL;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
++    if ((def = virDomainDefParseString(xml, privconn->xmlopt,
++                                       NULL, parse_flags)) == NULL)
+         goto cleanup;
+ 
+     if (bhyveDomainAssignAddresses(def, NULL) < 0)
diff -Nru libvirt-11.3.0/debian/patches/backport/ch-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/ch-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/ch-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/ch-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,180 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 16:23:30 +0100
+Subject: ch: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+This is one of the more complex ones since there is also a function that
+reads relevant metadata from a save image XML.  In order not to extract
+the parsing out of the function (and make the function basically trivial
+and all callers more complex) add a callback to the function which will
+be used to check the ACLs.  And since this function is called in APIs
+that perform ACL checks both with and without flags, add two of them for
+good measure.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit eb4322dfe8fff544d6dac01b2748c20f78f00d69)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/eb4322dfe8fff544d6dac01b2748c20f78f00d69
+---
+ src/ch/ch_driver.c | 76 +++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 53 insertions(+), 23 deletions(-)
+
+diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
+index 3bdcf66..14895a3 100644
+--- a/src/ch/ch_driver.c
++++ b/src/ch/ch_driver.c
+@@ -215,14 +215,19 @@ chDomainCreateXML(virConnectPtr conn,
+     if (flags & VIR_DOMAIN_START_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(vmdef = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        return NULL;
++
++    if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0)
++        return NULL;
++
++    g_clear_pointer(&vmdef, virDomainDefFree);
+ 
+     if ((vmdef = virDomainDefParseString(xml, driver->xmlopt,
+                                          NULL, parse_flags)) == NULL)
+         goto cleanup;
+ 
+-    if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0)
+-        goto cleanup;
+-
+     if (!(vm = virDomainObjListAdd(driver->domains,
+                                    &vmdef,
+                                    driver->xmlopt,
+@@ -346,6 +351,15 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (flags & VIR_DOMAIN_START_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(vmdef = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        return NULL;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0)
++        return NULL;
++
++    g_clear_pointer(&vmdef, virDomainDefFree);
++
+     if ((vmdef = virDomainDefParseString(xml, driver->xmlopt,
+                                          NULL, parse_flags)) == NULL)
+         goto cleanup;
+@@ -353,9 +367,6 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (virXMLCheckIllegalChars("name", vmdef->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0)
+-        goto cleanup;
+-
+     if (!(vm = virDomainObjListAdd(driver->domains, &vmdef,
+                                    driver->xmlopt,
+                                    0, &oldDef)))
+@@ -912,16 +923,24 @@ chDomainSaveXMLRead(int fd)
+     return g_steal_pointer(&xml);
+ }
+ 
+-static int chDomainSaveImageRead(virCHDriver *driver,
++static int chDomainSaveImageRead(virConnectPtr conn,
+                                  const char *path,
+-                                 virDomainDef **ret_def)
++                                 virDomainDef **ret_def,
++                                 unsigned int flags,
++                                 int (*ensureACL)(virConnectPtr, virDomainDef *),
++                                 int (*ensureACLWithFlags)(virConnectPtr,
++                                                           virDomainDef *,
++                                                           unsigned int))
+ {
++    virCHDriver *driver = conn->privateData;
+     g_autoptr(virCHDriverConfig) cfg = virCHDriverGetConfig(driver);
+     g_autoptr(virDomainDef) def = NULL;
+     g_autofree char *from = NULL;
+     g_autofree char *xml = NULL;
+     VIR_AUTOCLOSE fd = -1;
+     int ret = -1;
++    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
++                               VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+ 
+     from = g_strdup_printf("%s/%s", path, CH_SAVE_XML);
+     if ((fd = virFileOpenAs(from, O_RDONLY, 0, cfg->user, cfg->group, 0)) < 0) {
+@@ -934,9 +953,23 @@ static int chDomainSaveImageRead(virCHDriver *driver,
+     if (!(xml = chDomainSaveXMLRead(fd)))
+         goto end;
+ 
+-    if (!(def = virDomainDefParseString(xml, driver->xmlopt, NULL,
+-                                        VIR_DOMAIN_DEF_PARSE_INACTIVE |
+-                                        VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
++    if (ensureACL || ensureACLWithFlags) {
++        /* Parse only the IDs for ACL checks */
++        g_autoptr(virDomainDef) aclDef = virDomainDefIDsParseString(xml,
++                                                                    driver->xmlopt,
++                                                                    parse_flags);
++
++        if (!aclDef)
++            goto end;
++
++        if (ensureACL && ensureACL(conn, aclDef) < 0)
++            goto end;
++
++        if (ensureACLWithFlags && ensureACLWithFlags(conn, aclDef, flags) < 0)
++            goto end;
++    }
++
++    if (!(def = virDomainDefParseString(xml, driver->xmlopt, NULL, parse_flags)))
+         goto end;
+ 
+     *ret_def = g_steal_pointer(&def);
+@@ -957,10 +990,9 @@ chDomainSaveImageGetXMLDesc(virConnectPtr conn,
+ 
+     virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
+ 
+-    if (chDomainSaveImageRead(driver, path, &def) < 0)
+-        goto cleanup;
+-
+-    if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0)
++    if (chDomainSaveImageRead(conn, path, &def, flags,
++                              virDomainSaveImageGetXMLDescEnsureACL,
++                              NULL) < 0)
+         goto cleanup;
+ 
+     ret = virDomainDefFormat(def, driver->xmlopt,
+@@ -1060,10 +1092,9 @@ chDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
+         goto cleanup;
+ 
+     path = chDomainManagedSavePath(driver, vm);
+-    if (chDomainSaveImageRead(driver, path, &def) < 0)
+-        goto cleanup;
+-
+-    if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, def, flags) < 0)
++    if (chDomainSaveImageRead(dom->conn, path, &def, flags,
++                              NULL,
++                              virDomainManagedSaveGetXMLDescEnsureACL) < 0)
+         goto cleanup;
+ 
+     ret = virDomainDefFormat(def, driver->xmlopt,
+@@ -1115,10 +1146,9 @@ chDomainRestoreFlags(virConnectPtr conn,
+         return -1;
+     }
+ 
+-    if (chDomainSaveImageRead(driver, from, &def) < 0)
+-        goto cleanup;
+-
+-    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
++    if (chDomainSaveImageRead(conn, from, &def, flags,
++                              virDomainRestoreFlagsEnsureACL,
++                              NULL) < 0)
+         goto cleanup;
+ 
+     if (chDomainSaveRestoreAdditionalValidation(driver, def) < 0)
diff -Nru libvirt-11.3.0/debian/patches/backport/conf-Add-virDomainDefIDsParseString.patch libvirt-11.3.0/debian/patches/backport/conf-Add-virDomainDefIDsParseString.patch
--- libvirt-11.3.0/debian/patches/backport/conf-Add-virDomainDefIDsParseString.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/conf-Add-virDomainDefIDsParseString.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,91 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 14:33:31 +0100
+Subject: conf: Add virDomainDefIDsParseString
+
+This function performs only parsing with the underlying
+virDomainDefParseIDs() function to get needed metadata for any ACL
+checks, but nothing else to avoid extraneous allocations and any
+parser-induced DoS over ACL-forbidden connections.
+
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit e6de1e43ab6e907225b8f9bcea3772231908717e)
+
+CVE-2025-12784
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/e6de1e43ab6e907225b8f9bcea3772231908717e
+---
+ src/conf/domain_conf.c   | 29 +++++++++++++++++++++++++++++
+ src/conf/domain_conf.h   |  3 +++
+ src/libvirt_private.syms |  1 +
+ 3 files changed, 33 insertions(+)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 542d6ad..ca80431 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -20261,6 +20261,35 @@ virDomainDefParse(const char *xmlStr,
+     return virDomainDefParseNode(ctxt, xmlopt, parseOpaque, flags);
+ }
+ 
++virDomainDef *
++virDomainDefIDsParseString(const char *xmlStr,
++                           virDomainXMLOption *xmlopt,
++                           unsigned int flags)
++{
++    g_autoptr(virDomainDef) def = NULL;
++    g_autoptr(xmlDoc) xml = NULL;
++    g_autoptr(xmlXPathContext) ctxt = NULL;
++    bool uuid_generated = false;
++
++    xml = virXMLParseWithIndent(NULL, xmlStr, _("(domain_definition)"),
++                                "domain", &ctxt, "domain.rng", false);
++
++    if (!xml)
++        return NULL;
++
++    def = virDomainDefNew(xmlopt);
++    if (!def)
++        return NULL;
++
++    if (virDomainDefParseIDs(def, ctxt, flags, &uuid_generated) < 0)
++        return NULL;
++
++    if (uuid_generated)
++        memset(def->uuid, 0, VIR_UUID_BUFLEN);
++
++    return g_steal_pointer(&def);
++}
++
+ virDomainDef *
+ virDomainDefParseString(const char *xmlStr,
+                         virDomainXMLOption *xmlopt,
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 58b97a2..c33ead2 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -3900,6 +3900,9 @@ virDomainDiskDef *virDomainDiskDefParse(const char *xmlStr,
+ virStorageSource *virDomainDiskDefParseSource(const char *xmlStr,
+                                               virDomainXMLOption *xmlopt,
+                                               unsigned int flags);
++virDomainDef * virDomainDefIDsParseString(const char *xmlStr,
++                                          virDomainXMLOption *xmlopt,
++                                          unsigned int flags);
+ virDomainDef *virDomainDefParseString(const char *xmlStr,
+                                       virDomainXMLOption *xmlopt,
+                                       void *parseOpaque,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index a8ebf9e..0e62cc6 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -349,6 +349,7 @@ virDomainDefHasPCIHostdev;
+ virDomainDefHasUSB;
+ virDomainDefHasVcpusOffline;
+ virDomainDefHasVDPANet;
++virDomainDefIDsParseString;
+ virDomainDefLifecycleActionAllowed;
+ virDomainDefMaybeAddController;
+ virDomainDefMaybeAddInput;
diff -Nru libvirt-11.3.0/debian/patches/backport/libxl-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/libxl-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/libxl-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/libxl-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,73 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 15:43:57 +0100
+Subject: libxl: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit a1f48bca077e2f3377f29d746efd4310b8a2910f)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/a1f48bca077e2f3377f29d746efd4310b8a2910f
+---
+ src/libxl/libxl_driver.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
+index 0fb256e..7647163 100644
+--- a/src/libxl/libxl_driver.c
++++ b/src/libxl/libxl_driver.c
+@@ -1025,13 +1025,18 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml,
+     if (flags & VIR_DOMAIN_START_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
+-    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+-                                        NULL, parse_flags)))
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
+         goto cleanup;
+ 
+     if (virDomainCreateXMLEnsureACL(conn, def) < 0)
+         goto cleanup;
+ 
++    g_clear_pointer(&def, virDomainDefFree);
++
++    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
++                                        NULL, parse_flags)))
++        goto cleanup;
++
+     if (!(vm = virDomainObjListAdd(driver->domains, &def,
+                                    driver->xmlopt,
+                                    VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
+@@ -2811,6 +2816,14 @@ libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag
+     if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        goto cleanup;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
++        goto cleanup;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
+     if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+                                         NULL, parse_flags)))
+         goto cleanup;
+@@ -2818,9 +2831,6 @@ libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag
+     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (!(vm = virDomainObjListAdd(driver->domains, &def,
+                                    driver->xmlopt,
+                                    0,
diff -Nru libvirt-11.3.0/debian/patches/backport/lxc-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/lxc-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/lxc-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/lxc-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,75 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 15:49:01 +0100
+Subject: lxc: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit a6dcfee896f67bb8bdfdbb0b406ac7649fbb4c0f)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/a6dcfee896f67bb8bdfdbb0b406ac7649fbb4c0f
+---
+ src/lxc/lxc_driver.c | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index 80cf07d..c0a93c0 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -409,6 +409,15 @@ lxcDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
+         goto cleanup;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        goto cleanup;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
++        goto cleanup;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
+     if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+                                         NULL, parse_flags)))
+         goto cleanup;
+@@ -416,9 +425,6 @@ lxcDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
+         goto cleanup;
+ 
+@@ -1066,13 +1072,19 @@ lxcDomainCreateXMLWithFiles(virConnectPtr conn,
+     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
+         goto cleanup;
+ 
+-    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+-                                        NULL, parse_flags)))
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
+         goto cleanup;
+ 
+     if (virDomainCreateXMLWithFilesEnsureACL(conn, def) < 0)
+         goto cleanup;
+ 
++    g_clear_pointer(&def, virDomainDefFree);
++
++    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
++                                        NULL, parse_flags)))
++        goto cleanup;
++
+     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
+         goto cleanup;
+ 
diff -Nru libvirt-11.3.0/debian/patches/backport/qemu-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/qemu-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/qemu-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/qemu-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,397 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 14:33:41 +0100
+Subject: qemu: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+This is one of the more complex ones since there is also a function that
+reads relevant metadata from a save image XML.  In order _not_ to extract
+the parsing out of the function (and make the function basically trivial
+and all callers more complex) add a callback to the function which will
+be used to check the ACLs.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit 2a326c415a7e1cdd49989cc7e46b88d9ca90dd97)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/2a326c415a7e1cdd49989cc7e46b88d9ca90dd97
+---
+ src/qemu/qemu_driver.c    | 90 ++++++++++++++++++++++++-----------------------
+ src/qemu/qemu_migration.c | 23 +++++++++++-
+ src/qemu/qemu_migration.h |  4 ++-
+ src/qemu/qemu_saveimage.c | 25 ++++++++++---
+ src/qemu/qemu_saveimage.h |  4 ++-
+ src/qemu/qemu_snapshot.c  |  4 +--
+ 6 files changed, 97 insertions(+), 53 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 9f04374..36de702 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -1562,11 +1562,17 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
+     if (flags & VIR_DOMAIN_START_RESET_NVRAM)
+         start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM;
+ 
+-    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+-                                        NULL, parse_flags)))
+-        goto cleanup;
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        return NULL;
+ 
+     if (virDomainCreateXMLEnsureACL(conn, def) < 0)
++        return NULL;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
++    if (!(def = virDomainDefParseString(xml, driver->xmlopt,
++                                        NULL, parse_flags)))
+         goto cleanup;
+ 
+     if (!(vm = virDomainObjListAdd(driver->domains, &def,
+@@ -5784,7 +5790,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
+     if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM)
+         reset_nvram = true;
+ 
+-    if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
++    if (qemuSaveImageGetMetadata(driver, NULL, path, ensureACL, conn, &def, &data) < 0)
+         goto cleanup;
+ 
+     sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
+@@ -5797,9 +5803,6 @@ qemuDomainRestoreInternal(virConnectPtr conn,
+     if (fd < 0)
+         goto cleanup;
+ 
+-    if (ensureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
+         int hookret;
+ 
+@@ -5927,10 +5930,9 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
+ 
+     virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
+ 
+-    if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
+-        goto cleanup;
+-
+-    if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0)
++    if (qemuSaveImageGetMetadata(driver, NULL, path,
++                                 virDomainSaveImageGetXMLDescEnsureACL,
++                                 conn, &def, &data) < 0)
+         goto cleanup;
+ 
+     ret = qemuDomainDefFormatXML(driver, NULL, def, flags);
+@@ -5960,7 +5962,9 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
+     else if (flags & VIR_DOMAIN_SAVE_PAUSED)
+         state = 0;
+ 
+-    if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
++    if (qemuSaveImageGetMetadata(driver, NULL, path,
++                                 virDomainSaveImageDefineXMLEnsureACL,
++                                 conn, &def, &data) < 0)
+         goto cleanup;
+ 
+     fd = qemuSaveImageOpen(driver, path, false, false, NULL, true);
+@@ -5968,9 +5972,6 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
+     if (fd < 0)
+         goto cleanup;
+ 
+-    if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (STREQ(data->xml, dxml) &&
+         (state < 0 || state == data->header.was_running)) {
+         /* no change to the XML */
+@@ -6042,7 +6043,8 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
+         goto cleanup;
+     }
+ 
+-    if (qemuSaveImageGetMetadata(driver, priv->qemuCaps, path, &def, &data) < 0)
++    if (qemuSaveImageGetMetadata(driver, priv->qemuCaps, path,
++                                 NULL, NULL, &def, &data) < 0)
+         goto cleanup;
+ 
+     ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags);
+@@ -6106,7 +6108,7 @@ qemuDomainObjRestore(virConnectPtr conn,
+     bool sparse = false;
+     g_autoptr(qemuMigrationParams) restoreParams = NULL;
+ 
+-    ret = qemuSaveImageGetMetadata(driver, NULL, path, &def, &data);
++    ret = qemuSaveImageGetMetadata(driver, NULL, path, NULL, NULL, &def, &data);
+     if (ret < 0) {
+         if (qemuSaveImageIsCorrupt(driver, path)) {
+             if (unlink(path) < 0) {
+@@ -6468,6 +6470,15 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
+     if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        return NULL;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
++        return NULL;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
+     if (!(def = virDomainDefParseString(xml, driver->xmlopt,
+                                         NULL, parse_flags)))
+         return NULL;
+@@ -6475,9 +6486,6 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
+     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     if (!(vm = virDomainObjListAdd(driver->domains, &def,
+                                    driver->xmlopt,
+                                    0, &oldDef)))
+@@ -10794,10 +10802,9 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
+         return -1;
+     }
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepareTunnelEnsureACL)))
+         return -1;
+ 
+     return qemuMigrationDstPrepareTunnel(driver, dconn,
+@@ -10847,10 +10854,9 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
+         return -1;
+     }
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepare2EnsureACL)))
+         return -1;
+ 
+     /* Do not use cookies in v2 protocol, since the cookie
+@@ -11070,10 +11076,9 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
+                                                    QEMU_MIGRATION_DESTINATION)))
+         return -1;
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepare3EnsureACL)))
+         return -1;
+ 
+     return qemuMigrationDstPrepareDirect(driver, dconn,
+@@ -11173,10 +11178,9 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+         return -1;
+     }
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepare3ParamsEnsureACL)))
+         return -1;
+ 
+     return qemuMigrationDstPrepareDirect(driver, dconn,
+@@ -11218,10 +11222,9 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
+                                                    QEMU_MIGRATION_DESTINATION)))
+         return -1;
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepareTunnel3EnsureACL)))
+         return -1;
+ 
+     return qemuMigrationDstPrepareTunnel(driver, dconn,
+@@ -11270,10 +11273,9 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+                                                    QEMU_MIGRATION_DESTINATION)))
+         return -1;
+ 
+-    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname)))
+-        return -1;
+-
+-    if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
++    if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname,
++                                           dconn,
++                                           virDomainMigratePrepareTunnel3ParamsEnsureACL)))
+         return -1;
+ 
+     return qemuMigrationDstPrepareTunnel(driver, dconn,
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index bb4d74a..e40854f 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -4018,7 +4018,9 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver,
+                            virQEMUCaps *qemuCaps,
+                            const char *dom_xml,
+                            const char *dname,
+-                           char **origname)
++                           char **origname,
++                           virConnectPtr sconn,
++                           int (*ensureACL)(virConnectPtr, virDomainDef *))
+ {
+     virDomainDef *def;
+     char *name = NULL;
+@@ -4029,6 +4031,24 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver,
+         return NULL;
+     }
+ 
++    if (ensureACL) {
++        g_autoptr(virDomainDef) aclDef = NULL;
++
++        /* Avoid parsing the whole domain definition for ACL checks */
++        if (!(aclDef = virDomainDefIDsParseString(dom_xml, driver->xmlopt,
++                                                  VIR_DOMAIN_DEF_PARSE_INACTIVE)))
++            return NULL;
++
++        if (dname) {
++            VIR_FREE(aclDef->name);
++            aclDef->name = g_strdup(dname);
++        }
++
++        if (ensureACL(sconn, aclDef) < 0) {
++            return NULL;
++        }
++    }
++
+     if (!(def = virDomainDefParseString(dom_xml, driver->xmlopt,
+                                         qemuCaps,
+                                         VIR_DOMAIN_DEF_PARSE_INACTIVE)))
+@@ -4957,6 +4977,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
+             if (!(persistDef = qemuMigrationAnyPrepareDef(driver,
+                                                           priv->qemuCaps,
+                                                           persist_xml,
++                                                          NULL, NULL,
+                                                           NULL, NULL)))
+                 goto error;
+         } else {
+diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
+index beb8881..cc6b400 100644
+--- a/src/qemu/qemu_migration.h
++++ b/src/qemu/qemu_migration.h
+@@ -134,7 +134,9 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver,
+                            virQEMUCaps *qemuCaps,
+                            const char *dom_xml,
+                            const char *dname,
+-                           char **origname);
++                           char **origname,
++                           virConnectPtr sconn,
++                           int (*ensureACL)(virConnectPtr, virDomainDef *));
+ 
+ int
+ qemuMigrationDstPrepareTunnel(virQEMUDriver *driver,
+diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
+index a6a5fb4..998e8f0 100644
+--- a/src/qemu/qemu_saveimage.c
++++ b/src/qemu/qemu_saveimage.c
+@@ -614,16 +614,21 @@ qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path)
+  * @driver: qemu driver data
+  * @qemuCaps: pointer to qemuCaps if the domain is running or NULL
+  * @path: path of the save image
++ * @ensureACL: ACL callback to check against the definition or NULL
++ * @conn: parameter for the @ensureACL callback
+  * @ret_def: returns domain definition created from the XML stored in the image
+  * @ret_data: returns structure filled with data from the image header
+  *
+- * Open the save image file, read libvirt's save image metadata, and populate
+- * the @ret_def and @ret_data structures. Returns 0 on success and -1 on failure.
++ * Open the save image file, read libvirt's save image metadata, optionally
++ * check ACLs before parsing the whole domain definition and populate the
++ * @ret_def and @ret_data structures. Returns 0 on success and -1 on failure.
+  */
+ int
+ qemuSaveImageGetMetadata(virQEMUDriver *driver,
+                          virQEMUCaps *qemuCaps,
+                          const char *path,
++                         int (*ensureACL)(virConnectPtr, virDomainDef *),
++                         virConnectPtr conn,
+                          virDomainDef **ret_def,
+                          virQEMUSaveData **ret_data)
+ {
+@@ -631,6 +636,8 @@ qemuSaveImageGetMetadata(virQEMUDriver *driver,
+     VIR_AUTOCLOSE fd = -1;
+     virQEMUSaveData *data;
+     g_autoptr(virDomainDef) def = NULL;
++    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
++                               VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+     int rc;
+ 
+     if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0)
+@@ -640,10 +647,20 @@ qemuSaveImageGetMetadata(virQEMUDriver *driver,
+         return rc;
+ 
+     data = *ret_data;
++
++    if (ensureACL) {
++        /* Parse only the IDs for ACL checks */
++        g_autoptr(virDomainDef) aclDef = virDomainDefIDsParseString(data->xml,
++                                                                    driver->xmlopt,
++                                                                    parse_flags);
++
++        if (!aclDef || ensureACL(conn, aclDef) < 0)
++            return -1;
++    }
++
+     /* Create a domain from this XML */
+     if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps,
+-                                        VIR_DOMAIN_DEF_PARSE_INACTIVE |
+-                                        VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
++                                        parse_flags)))
+         return -1;
+ 
+     *ret_def = g_steal_pointer(&def);
+diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
+index 89c6941..15b73eb 100644
+--- a/src/qemu/qemu_saveimage.h
++++ b/src/qemu/qemu_saveimage.h
+@@ -98,9 +98,11 @@ int
+ qemuSaveImageGetMetadata(virQEMUDriver *driver,
+                          virQEMUCaps *qemuCaps,
+                          const char *path,
++                         int (*ensureACL)(virConnectPtr, virDomainDef *),
++                         virConnectPtr conn,
+                          virDomainDef **ret_def,
+                          virQEMUSaveData **ret_data)
+-    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
++    ATTRIBUTE_NONNULL(6) ATTRIBUTE_NONNULL(7);
+ 
+ int
+ qemuSaveImageOpen(virQEMUDriver *driver,
+diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
+index f9b18f9..373fe45 100644
+--- a/src/qemu/qemu_snapshot.c
++++ b/src/qemu/qemu_snapshot.c
+@@ -2403,8 +2403,8 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm,
+         g_autoptr(virDomainDef) savedef = NULL;
+ 
+         memdata->path = snapdef->memorysnapshotfile;
+-        if (qemuSaveImageGetMetadata(driver, NULL, memdata->path, &savedef,
+-                                     &memdata->data) < 0)
++        if (qemuSaveImageGetMetadata(driver, NULL, memdata->path, NULL, NULL,
++                                     &savedef, &memdata->data) < 0)
+             return -1;
+ 
+         memdata->fd = qemuSaveImageOpen(driver, memdata->path,
diff -Nru libvirt-11.3.0/debian/patches/backport/qemuDomainPrepareDiskSourceData-Setup-detect_zeroes-for-a.patch libvirt-11.3.0/debian/patches/backport/qemuDomainPrepareDiskSourceData-Setup-detect_zeroes-for-a.patch
--- libvirt-11.3.0/debian/patches/backport/qemuDomainPrepareDiskSourceData-Setup-detect_zeroes-for-a.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/qemuDomainPrepareDiskSourceData-Setup-detect_zeroes-for-a.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,166 @@
+From: Peter Krempa <pkrempa at redhat.com>
+Date: Fri, 14 Nov 2025 16:05:06 +0100
+Subject: qemuDomainPrepareDiskSourceData: Setup 'detect_zeroes' for all
+ layers
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+While it may seem that zero detection is pointless for backing chain
+layers other than the top one, which is usually the only one gettin
+written to,  with block operations such as active-layer commit the
+non-top layer may become active, in which case the VM wouldn't be
+configured in accordance to the XML any more.
+
+Similarly with snapshots a new image is introduced which would not get
+zero detection enabled, but next start of the VM would enable it.
+
+Fix this by propagating the zero detection setting for all layers.
+
+This problem partially addresses one of the issues reported in
+https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1120389
+
+Fixes: 8a78f88a1a6 and a522c3044bd (effectively reverts them)
+Signed-off-by: Peter Krempa <pkrempa at redhat.com>
+Reviewed-by: J?n Tomko <jtomko at redhat.com>
+Reviewed-by: Andrea Bolognani <abologna at redhat.com>
+(cherry picked from commit 475ed7075d400347f7e1b0f49ce1d1a39798ef99)
+
+Bug-Debian: https://bugs.debian.org/1121280
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/475ed7075d400347f7e1b0f49ce1d1a39798ef99
+---
+ src/qemu/qemu_domain.c                                              | 6 +-----
+ tests/qemublocktestdata/xml2json/file-backing_basic-detect.json     | 3 +++
+ .../qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json | 3 +++
+ .../qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json | 3 +++
+ tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args         | 6 +++---
+ 5 files changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 52da234..37317fc 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -9555,11 +9555,7 @@ qemuDomainPrepareDiskSourceData(virDomainDiskDef *disk,
+     if (!disk)
+         return;
+ 
+-    /* transfer properties valid only for the top level image */
+-    if (src == disk->src || src == disk->src->dataFileStore)
+-        src->detect_zeroes = disk->detect_zeroes;
+-
+-    /* transfer properties valid for the full chain */
++    src->detect_zeroes = disk->detect_zeroes;
+     src->iomode = disk->iomode;
+     src->cachemode = disk->cachemode;
+     src->discard = disk->discard;
+diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json b/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json
+index c272332..773b7b3 100644
+--- a/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json
++++ b/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json
+@@ -16,6 +16,7 @@
+ {
+   "node-name": "node-b-f",
+   "read-only": true,
++  "detect-zeroes": "on",
+   "driver": "qed",
+   "file": "node-b-s",
+   "backing": "node-c-f"
+@@ -30,6 +31,7 @@
+ {
+   "node-name": "node-c-f",
+   "read-only": true,
++  "detect-zeroes": "on",
+   "driver": "vmdk",
+   "file": "node-c-s",
+   "backing": "node-d-f"
+@@ -49,6 +51,7 @@
+ {
+   "node-name": "node-d-f",
+   "read-only": true,
++  "detect-zeroes": "on",
+   "driver": "raw",
+   "file": "node-d-s"
+ }
+diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json
+index 1ec0b8f..70faaa8 100644
+--- a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json
++++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json
+@@ -18,6 +18,7 @@
+   "node-name": "node-b-f",
+   "read-only": true,
+   "discard": "unmap",
++  "detect-zeroes": "unmap",
+   "driver": "qed",
+   "file": "node-b-s",
+   "backing": "node-c-f"
+@@ -33,6 +34,7 @@
+   "node-name": "node-c-f",
+   "read-only": true,
+   "discard": "unmap",
++  "detect-zeroes": "unmap",
+   "driver": "vmdk",
+   "file": "node-c-s",
+   "backing": "node-d-f"
+@@ -53,6 +55,7 @@
+   "node-name": "node-d-f",
+   "read-only": true,
+   "discard": "unmap",
++  "detect-zeroes": "unmap",
+   "driver": "raw",
+   "file": "node-d-s"
+ }
+diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json
+index 315a173..4bb964a 100644
+--- a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json
++++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json
+@@ -18,6 +18,7 @@
+   "node-name": "node-b-f",
+   "read-only": true,
+   "discard": "ignore",
++  "detect-zeroes": "on",
+   "driver": "qed",
+   "file": "node-b-s",
+   "backing": "node-c-f"
+@@ -33,6 +34,7 @@
+   "node-name": "node-c-f",
+   "read-only": true,
+   "discard": "ignore",
++  "detect-zeroes": "on",
+   "driver": "vmdk",
+   "file": "node-c-s",
+   "backing": "node-d-f"
+@@ -53,6 +55,7 @@
+   "node-name": "node-d-f",
+   "read-only": true,
+   "discard": "ignore",
++  "detect-zeroes": "on",
+   "driver": "raw",
+   "file": "node-d-s"
+ }
+diff --git a/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args b/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
+index d959d4a..6284c08 100644
+--- a/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
++++ b/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
+@@ -28,17 +28,17 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-test/.config \
+ -boot menu=on,strict=on \
+ -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-unmap-back.img","node-name":"libvirt-7-storage","auto-read-only":true,"discard":"unmap"}' \
+--blockdev '{"node-name":"libvirt-7-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-7-storage","backing":null}' \
++-blockdev '{"node-name":"libvirt-7-format","read-only":true,"discard":"unmap","detect-zeroes":"unmap","driver":"qcow2","file":"libvirt-7-storage","backing":null}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-unmap.img","node-name":"libvirt-6-storage","auto-read-only":true,"discard":"unmap"}' \
+ -blockdev '{"node-name":"libvirt-6-format","read-only":false,"discard":"unmap","detect-zeroes":"unmap","driver":"qcow2","file":"libvirt-6-storage","backing":"libvirt-7-format"}' \
+ -device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-6-format","id":"virtio-disk0","bootindex":2}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-on-back.img","node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
+--blockdev '{"node-name":"libvirt-5-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-5-storage","backing":null}' \
++-blockdev '{"node-name":"libvirt-5-format","read-only":true,"discard":"unmap","detect-zeroes":"on","driver":"qcow2","file":"libvirt-5-storage","backing":null}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-on.img","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
+ -blockdev '{"node-name":"libvirt-4-format","read-only":false,"discard":"unmap","detect-zeroes":"on","driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-format"}' \
+ -device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-4-format","id":"virtio-disk1"}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-off-back.img","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+--blockdev '{"node-name":"libvirt-3-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-3-storage","backing":null}' \
++-blockdev '{"node-name":"libvirt-3-format","read-only":true,"discard":"unmap","detect-zeroes":"off","driver":"qcow2","file":"libvirt-3-storage","backing":null}' \
+ -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-off.img","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+ -blockdev '{"node-name":"libvirt-2-format","read-only":false,"discard":"unmap","detect-zeroes":"off","driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"}' \
+ -device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x6","drive":"libvirt-2-format","id":"virtio-disk2"}' \
diff -Nru libvirt-11.3.0/debian/patches/backport/qemu-snapshot-Set-umask-for-qemu-img-when-creating-extern.patch libvirt-11.3.0/debian/patches/backport/qemu-snapshot-Set-umask-for-qemu-img-when-creating-extern.patch
--- libvirt-11.3.0/debian/patches/backport/qemu-snapshot-Set-umask-for-qemu-img-when-creating-extern.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/qemu-snapshot-Set-umask-for-qemu-img-when-creating-extern.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,40 @@
+From: Peter Krempa <pkrempa at redhat.com>
+Date: Wed, 12 Nov 2025 17:52:05 +0100
+Subject: qemu: snapshot: Set umask for 'qemu-img' when creating external
+ inactive snapshots
+
+External inactive snapshots are created by invoking 'qemu-img' which
+creates the file. Currently qemu-img creates image with mode 644 based
+on default umask as libvirt doesn't set any.
+
+Having a world-readable image is obviously wrong so set the umask to
+077 to have the file readable only by the owner.
+
+Resolves: https://bugs.debian.org/1120119
+Signed-off-by: Peter Krempa <pkrempa at redhat.com>
+(cherry picked from commit a379327d8abcde8ac8d3e16fe5e4ba6f790d767a)
+
+CVE-2025-13193
+
+Bug-Debian: https://bugs.debian.org/1120119
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/a379327d8abcde8ac8d3e16fe5e4ba6f790d767a
+---
+ src/qemu/qemu_snapshot.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
+index 373fe45..6a95f3e 100644
+--- a/src/qemu/qemu_snapshot.c
++++ b/src/qemu/qemu_snapshot.c
+@@ -228,6 +228,9 @@ qemuSnapshotCreateQcow2Files(virDomainDef *def,
+                                          NULL)))
+             return -1;
+ 
++        /* ensure that new files are only readable by the user */
++        virCommandSetUmask(cmd, 0077);
++
+         /* adds cmd line arg: backing_fmt=format,backing_file=/path/to/backing/file */
+         virBufferAsprintf(&buf, "backing_fmt=%s,backing_file=",
+                           virStorageFileFormatTypeToString(defdisk->src->format));
diff -Nru libvirt-11.3.0/debian/patches/backport/qemuxmlconftest-Improve-coverage-of-disk-detect-zeroes-te.patch libvirt-11.3.0/debian/patches/backport/qemuxmlconftest-Improve-coverage-of-disk-detect-zeroes-te.patch
--- libvirt-11.3.0/debian/patches/backport/qemuxmlconftest-Improve-coverage-of-disk-detect-zeroes-te.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/qemuxmlconftest-Improve-coverage-of-disk-detect-zeroes-te.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,102 @@
+From: Peter Krempa <pkrempa at redhat.com>
+Date: Fri, 14 Nov 2025 16:13:55 +0100
+Subject: qemuxmlconftest: Improve coverage of 'disk-detect-zeroes' test case
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Add test cases for all three options 'off'/'on'/'unmap' as well as add
+backing store for each image to show how the configuration behaves.
+
+Signed-off-by: Peter Krempa <pkrempa at redhat.com>
+Reviewed-by: J?n Tomko <jtomko at redhat.com>
+Reviewed-by: Andrea Bolognani <abologna at redhat.com>
+(cherry picked from commit 312be5eb9acfc3bbf164583ed7ed1d3b89698c5a)
+
+Bug-Debian: https://bugs.debian.org/1121280
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/312be5eb9acfc3bbf164583ed7ed1d3b89698c5a
+---
+ .../disk-detect-zeroes.x86_64-latest.args          | 20 +++++++++++---
+ tests/qemuxmlconfdata/disk-detect-zeroes.xml       | 31 ++++++++++++++++++++--
+ 2 files changed, 45 insertions(+), 6 deletions(-)
+
+diff --git a/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args b/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
+index 07acc46..d959d4a 100644
+--- a/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
++++ b/tests/qemuxmlconfdata/disk-detect-zeroes.x86_64-latest.args
+@@ -27,10 +27,22 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-test/.config \
+ -no-shutdown \
+ -boot menu=on,strict=on \
+ -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+--blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/f14.img","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+--blockdev '{"node-name":"libvirt-2-format","read-only":false,"discard":"unmap","detect-zeroes":"unmap","driver":"qcow2","file":"libvirt-2-storage"}' \
+--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-2-format","id":"virtio-disk0","bootindex":2}' \
+--blockdev '{"driver":"file","filename":"/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso","node-name":"libvirt-1-storage","read-only":true,"discard":"ignore","detect-zeroes":"on"}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-unmap-back.img","node-name":"libvirt-7-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-7-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-7-storage","backing":null}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-unmap.img","node-name":"libvirt-6-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-6-format","read-only":false,"discard":"unmap","detect-zeroes":"unmap","driver":"qcow2","file":"libvirt-6-storage","backing":"libvirt-7-format"}' \
++-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-6-format","id":"virtio-disk0","bootindex":2}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-on-back.img","node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-5-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-5-storage","backing":null}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-on.img","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-4-format","read-only":false,"discard":"unmap","detect-zeroes":"on","driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-format"}' \
++-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-4-format","id":"virtio-disk1"}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-off-back.img","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-3-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-3-storage","backing":null}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/detect-zeroes-off.img","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
++-blockdev '{"node-name":"libvirt-2-format","read-only":false,"discard":"unmap","detect-zeroes":"off","driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"}' \
++-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x6","drive":"libvirt-2-format","id":"virtio-disk2"}' \
++-blockdev '{"driver":"file","filename":"/var/lib/libvirt/detect-zeroes-cdrom.iso","node-name":"libvirt-1-storage","read-only":true,"discard":"ignore","detect-zeroes":"on"}' \
+ -device '{"driver":"ide-cd","bus":"ide.1","unit":0,"drive":"libvirt-1-storage","id":"ide0-1-0","bootindex":1}' \
+ -audiodev '{"id":"audio1","driver":"none"}' \
+ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \
+diff --git a/tests/qemuxmlconfdata/disk-detect-zeroes.xml b/tests/qemuxmlconfdata/disk-detect-zeroes.xml
+index ca3732c..3ea15c3 100644
+--- a/tests/qemuxmlconfdata/disk-detect-zeroes.xml
++++ b/tests/qemuxmlconfdata/disk-detect-zeroes.xml
+@@ -21,13 +21,40 @@
+     <emulator>/usr/bin/qemu-system-x86_64</emulator>
+     <disk type='file' device='disk'>
+       <driver name='qemu' type='qcow2' discard='unmap' detect_zeroes='unmap'/>
+-      <source file='/var/lib/libvirt/images/f14.img'/>
++      <source file='/var/lib/libvirt/images/detect-zeroes-unmap.img'/>
++      <backingStore type='file'>
++        <format type='qcow2'/>
++        <source file='/var/lib/libvirt/images/detect-zeroes-unmap-back.img'/>
++        <backingStore/>
++      </backingStore>
+       <target dev='vda' bus='virtio'/>
+       <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+     </disk>
++    <disk type='file' device='disk'>
++      <driver name='qemu' type='qcow2' discard='unmap' detect_zeroes='on'/>
++      <source file='/var/lib/libvirt/images/detect-zeroes-on.img'/>
++      <backingStore type='file'>
++        <format type='qcow2'/>
++        <source file='/var/lib/libvirt/images/detect-zeroes-on-back.img'/>
++        <backingStore/>
++      </backingStore>
++      <target dev='vdb' bus='virtio'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
++    </disk>
++    <disk type='file' device='disk'>
++      <driver name='qemu' type='qcow2' discard='unmap' detect_zeroes='off'/>
++      <source file='/var/lib/libvirt/images/detect-zeroes-off.img'/>
++      <backingStore type='file'>
++        <format type='qcow2'/>
++        <source file='/var/lib/libvirt/images/detect-zeroes-off-back.img'/>
++        <backingStore/>
++      </backingStore>
++      <target dev='vdc' bus='virtio'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
++    </disk>
+     <disk type='file' device='cdrom'>
+       <driver name='qemu' type='raw' discard='ignore' detect_zeroes='unmap'/>
+-      <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
++      <source file='/var/lib/libvirt/detect-zeroes-cdrom.iso'/>
+       <target dev='hdc' bus='ide'/>
+       <readonly/>
+       <address type='drive' controller='0' bus='1' target='0' unit='0'/>
diff -Nru libvirt-11.3.0/debian/patches/backport/vz-Check-ACLs-before-parsing-the-whole-domain-XML.patch libvirt-11.3.0/debian/patches/backport/vz-Check-ACLs-before-parsing-the-whole-domain-XML.patch
--- libvirt-11.3.0/debian/patches/backport/vz-Check-ACLs-before-parsing-the-whole-domain-XML.patch	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-11.3.0/debian/patches/backport/vz-Check-ACLs-before-parsing-the-whole-domain-XML.patch	2025-11-25 01:07:00.000000000 +0100
@@ -0,0 +1,66 @@
+From: Martin Kletzander <mkletzan at redhat.com>
+Date: Thu, 6 Nov 2025 16:03:26 +0100
+Subject: vz: Check ACLs before parsing the whole domain XML
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Utilise the new virDomainDefIDsParseString() for that.
+
+Fixes: CVE-2025-12748
+Reported-by: ????????? ??????? <s.tereshin at fobos-nt.ru>
+Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
+(cherry picked from commit 7285c10a7e70c430f85af7a2b3954892ab3c6d6b)
+
+Bug-Debian: https://bugs.debian.org/1120584
+
+Forwarded: not-needed
+Origin: https://gitlab.com/libvirt/libvirt/-/commits/7285c10a7e70c430f85af7a2b3954892ab3c6d6b
+---
+ src/vz/vz_driver.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
+index 571735f..2d8878f 100644
+--- a/src/vz/vz_driver.c
++++ b/src/vz/vz_driver.c
+@@ -789,6 +789,15 @@ vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
+         parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
+ 
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags)))
++        return NULL;
++
++    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
++        return NULL;
++
++    g_clear_pointer(&def, virDomainDefFree);
++
+     if ((def = virDomainDefParseString(xml, driver->xmlopt,
+                                        NULL, parse_flags)) == NULL)
+         goto cleanup;
+@@ -796,9 +805,6 @@ vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
+     if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
+         goto cleanup;
+ 
+-    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
+-        goto cleanup;
+-
+     dom = virDomainObjListFindByUUID(driver->domains, def->uuid);
+     if (dom == NULL) {
+         virResetLastError();
+@@ -2966,9 +2972,9 @@ vzDomainMigratePrepare3Params(virConnectPtr conn,
+                      | VZ_MIGRATION_COOKIE_DOMAIN_NAME) < 0)
+         return -1;
+ 
+-    if (!(def = virDomainDefParseString(dom_xml, driver->xmlopt,
+-                                        NULL,
+-                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
++    /* Avoid parsing the whole domain definition for ACL checks */
++    if (!(def = virDomainDefIDsParseString(dom_xml, driver->xmlopt,
++                                           VIR_DOMAIN_DEF_PARSE_INACTIVE)))
+         return -1;
+ 
+     if (dname) {
diff -Nru libvirt-11.3.0/debian/patches/series libvirt-11.3.0/debian/patches/series
--- libvirt-11.3.0/debian/patches/series	2025-11-02 16:54:31.000000000 +0100
+++ libvirt-11.3.0/debian/patches/series	2025-11-25 01:07:00.000000000 +0100
@@ -5,6 +5,16 @@
 backport/tests-virnettls-test-Drop-use-of-GNUTLS_KEY_KEY_ENCIPHERM.patch
 backport/daemon-Drop-log-level-of-VIR_ERR_NO_SUPPORT-to-debug.patch
 backport/qemu-capabilities-Check-if-cpuModels-is-not-NULL-before-t.patch
+backport/conf-Add-virDomainDefIDsParseString.patch
+backport/bhyve-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/libxl-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/lxc-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/vz-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/ch-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/qemu-Check-ACLs-before-parsing-the-whole-domain-XML.patch
+backport/qemu-snapshot-Set-umask-for-qemu-img-when-creating-extern.patch
+backport/qemuxmlconftest-Improve-coverage-of-disk-detect-zeroes-te.patch
+backport/qemuDomainPrepareDiskSourceData-Setup-detect_zeroes-for-a.patch
 debian/Debianize-libvirt-guests.patch
 debian/apparmor_profiles_local_include.patch
 debian/Use-sensible-editor-by-default.patch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-libvirt-maintainers/attachments/20251127/d40b7f83/attachment-0001.sig>


More information about the Pkg-libvirt-maintainers mailing list