Xen Security Advisory 476 v1 (CVE-2025-58149) - Incorrect removal of permissions on PCI device unplug

Xen.org security team posted 1 patch 5 days, 7 hours ago
Failed in applying to current master (apply log)
Xen Security Advisory 476 v1 (CVE-2025-58149) - Incorrect removal of permissions on PCI device unplug
Posted by Xen.org security team 5 days, 7 hours ago
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

            Xen Security Advisory CVE-2025-58149 / XSA-476

         Incorrect removal of permissions on PCI device unplug

ISSUE DESCRIPTION
=================

When passing through PCI devices, the detach logic in libxl won't remove
access permissions to any 64bit memory BARs the device might have.  As a
result a domain can still have access any 64bit memory BAR when such
device is no longer assigned to the domain.

For PV domains the permission leak allows the domain itself to map the memory
in the page-tables.  For HVM it would require a compromised device model or
stubdomain to map the leaked memory into the HVM domain p2m.

IMPACT
======

A buggy or malicious PV guest can access memory of PCI devices no longer
assigned to it.

VULNERABLE SYSTEMS
==================

Xen versions 4.0 and newer are vulnerable.

Only PV guests with PCI passthrough devices can leverage the vulnerability.

Only domains whose PCI devices are managed by the libxl library are affected.
This includes the xl toolstack and xapi, which uses the xl toolstack when
dealing with PCI devices.

HVM guests are also affected, but accessing the leaked memory requires an
additional compromised component on the system.

MITIGATION
==========

Not doing hot unplug of PCI devices will avoid the vulnerability.

Passing through PCI devices to HVM domains only will also limit the impact, as
an attacker would require another compromised component to exploit it.

CREDITS
=======

This issue was discovered by Jiqian Chen of AMD and diagnosed as a
security issue by Roger Pau Monné of XenServer.

RESOLUTION
==========

Applying the attached patch resolves this issue.

Note that patches for released versions are generally prepared to
apply to the stable branches, and may not apply cleanly to the most
recent release tarball.  Downstreams are encouraged to update to the
tip of the stable branch before applying these patches.

xsa476.patch           xen-unstable
xsa476-4.20.patch      Xen 4.20.x - Xen 4.18.x
xsa476-4.17.patch      Xen 4.17.x

$ sha256sum xsa476*
ee4c2fa73d38c5c699006b6317ba53f20343af0593ff9a8c38e7e59b69a0beca  xsa476.patch
3b921545f023dc7d9d943d0d661e677711458a917630de14f0871b03db0f2148  xsa476-4.17.patch
5babfaa3680de9950d3391a78e4956b5c18d54eaac9938c6cde2433a2ad3f27d  xsa476-4.20.patch
$

NOTE REGARDING LACK OF EMBARGO
==============================

This issue was discussed in public already.
-----BEGIN PGP SIGNATURE-----

iQFABAEBCAAqFiEEI+MiLBRfRHX6gGCng/4UyVfoK9kFAmj7bXYMHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZEIEH/ApNvYmMcqqEyOMgGV/VVmEMcXsAy1Ps3rMdDe9U
YLsa7ugJLQ/kMI70y0qzws8Uc/kVftl6Z3NbvhpnBMdpurEbZnVuuPtV5I08BF7G
23Qij+NNXSFdUzZVtgqz+POuhpVmrZgEwmg2HXsL1h2KgirUgwh5Nbs4ZuAlbz/f
05tiljIdv4ntqz8sczUxUmtw3XuzcTu0GS8EtPSoAEC5paK72X+5i496qDKpgtqv
gdnxqDL2s5ue3G029e9JA3pscVQTMYa3InNiHK28GAM2BW10op1JaxVl/JLN1zzL
igpd+u6Fs73qNzcClXQ48YEBkCoTTIdhIrl0mSp4zTfN9dk=
=MBxa
-----END PGP SIGNATURE-----
From: Jiqian Chen <Jiqian.Chen@amd.com>
Subject: tools/libs/light: fix BAR memory address truncation

64-bit BAR memory address is truncated when removing a passthrough
pci device from guest since it uses "unsigned int".

So, change to use 64-bit type to fix this problem.

This is XSA-476 / CVE-2025-58149.

Fixes: b0a1af61678b ("libxenlight: implement pci passthrough")
Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>

diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 2ea2caeb6624..49d272d0de65 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -2001,7 +2001,8 @@ static void pci_remove_detached(libxl__egc *egc,
 {
     STATE_AO_GC(prs->aodev->ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    unsigned int start = 0, end = 0, flags = 0, size = 0, irq = 0;
+    uint64_t start = 0, end = 0, flags = 0, size = 0;
+    unsigned int irq = 0;
     int i, stubdomid = 0;
     const char *sysfs_path;
     FILE *f;
@@ -2031,7 +2032,8 @@ static void pci_remove_detached(libxl__egc *egc,
     }
 
     for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-        if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
+        if (fscanf(f, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64"\n",
+                   &start, &end, &flags) != 3)
             continue;
         size = end - start + 1;
         if (start) {
@@ -2040,7 +2042,7 @@ static void pci_remove_detached(libxl__egc *egc,
                                                  size, 0);
                 if (rc < 0)
                     LOGED(ERROR, domid,
-                          "xc_domain_ioport_permission error 0x%x/0x%x",
+                          "xc_domain_ioport_permission error %#"PRIx64"/%#"PRIx64,
                           start,
                           size);
             } else {
@@ -2050,7 +2052,7 @@ static void pci_remove_detached(libxl__egc *egc,
                                                 0);
                 if (rc < 0)
                     LOGED(ERROR, domid,
-                          "xc_domain_iomem_permission error 0x%x/0x%x",
+                          "xc_domain_iomem_permission error %#"PRIx64"/%#"PRIx64,
                           start,
                           size);
             }
From: Jiqian Chen <Jiqian.Chen@amd.com>
Subject: tools/libs/light: fix BAR memory address truncation

64-bit BAR memory address is truncated when removing a passthrough
pci device from guest since it uses "unsigned int".

So, change to use 64-bit type to fix this problem.

This is XSA-476 / CVE-2025-58149.

Fixes: b0a1af61678b ("libxenlight: implement pci passthrough")
Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>

diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index f4c4f175454d..37e2e262477e 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -1995,7 +1995,7 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
         char *sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
                                      pci->bus, pci->dev, pci->func);
         FILE *f = fopen(sysfs_path, "r");
-        unsigned int start = 0, end = 0, flags = 0, size = 0;
+        uint64_t start = 0, end = 0, flags = 0, size = 0;
         int irq = 0;
         int i;
 
@@ -2004,7 +2004,8 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
             goto skip1;
         }
         for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
+            if (fscanf(f, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64"\n",
+                       &start, &end, &flags) != 3)
                 continue;
             size = end - start + 1;
             if (start) {
@@ -2012,7 +2013,7 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
                     rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0);
                     if (rc < 0)
                         LOGED(ERROR, domainid,
-                              "xc_domain_ioport_permission error 0x%x/0x%x",
+                              "xc_domain_ioport_permission error %#"PRIx64"/%#"PRIx64,
                               start,
                               size);
                 } else {
@@ -2020,7 +2021,7 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
                                                     (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
                     if (rc < 0)
                         LOGED(ERROR, domainid,
-                              "xc_domain_iomem_permission error 0x%x/0x%x",
+                              "xc_domain_iomem_permission error %#"PRIx64"/%#"PRIx64,
                               start,
                               size);
                 }
From: Jiqian Chen <Jiqian.Chen@amd.com>
Subject: tools/libs/light: fix BAR memory address truncation

64-bit BAR memory address is truncated when removing a passthrough
pci device from guest since it uses "unsigned int".

So, change to use 64-bit type to fix this problem.

This is XSA-476 / CVE-2025-58149.

Fixes: b0a1af61678b ("libxenlight: implement pci passthrough")
Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>

diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 1647fd6f4756..7af602224aba 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -2179,7 +2179,7 @@ static void pci_remove_detached(libxl__egc *egc,
 {
     STATE_AO_GC(prs->aodev->ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    unsigned int start = 0, end = 0, flags = 0, size = 0;
+    uint64_t start = 0, end = 0, flags = 0, size = 0;
     int  irq = 0, i, stubdomid = 0;
     const char *sysfs_path;
     FILE *f;
@@ -2209,7 +2209,8 @@ static void pci_remove_detached(libxl__egc *egc,
     }
 
     for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-        if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
+        if (fscanf(f, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64"\n",
+                   &start, &end, &flags) != 3)
             continue;
         size = end - start + 1;
         if (start) {
@@ -2218,7 +2219,7 @@ static void pci_remove_detached(libxl__egc *egc,
                                                  size, 0);
                 if (rc < 0)
                     LOGED(ERROR, domid,
-                          "xc_domain_ioport_permission error 0x%x/0x%x",
+                          "xc_domain_ioport_permission error %#"PRIx64"/%#"PRIx64,
                           start,
                           size);
             } else {
@@ -2228,7 +2229,7 @@ static void pci_remove_detached(libxl__egc *egc,
                                                 0);
                 if (rc < 0)
                     LOGED(ERROR, domid,
-                          "xc_domain_iomem_permission error 0x%x/0x%x",
+                          "xc_domain_iomem_permission error %#"PRIx64"/%#"PRIx64,
                           start,
                           size);
             }