Xen Security Advisory 473 v2 (CVE-2025-58144,CVE-2025-58145) - Arm issues with page refcounting

Xen.org security team posted 1 patch 4 days, 15 hours ago
Failed in applying to current master (apply log)
Xen Security Advisory 473 v2 (CVE-2025-58144,CVE-2025-58145) - Arm issues with page refcounting
Posted by Xen.org security team 4 days, 15 hours ago
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

     Xen Security Advisory CVE-2025-58144,CVE-2025-58145 / XSA-473
                               version 2

                   Arm issues with page refcounting

UPDATES IN VERSION 2
====================

Public release.

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

There are two issues related to the mapping of pages belonging to other
domains: For one, an assertion is wrong there, where the case actually
needs handling.  A NULL pointer de-reference could result on a release
build.  This is CVE-2025-58144.

And then the P2M lock isn't held until a page reference was actually
obtained (or the attempt to do so has failed).  Otherwise the page can
not only change type, but even ownership in between, thus allowing
domain boundaries to be violated.  This is CVE-2025-58145.

IMPACT
======

An unprivileged guest can cause a hypervisor crash, causing a Denial of
Service (DoS) of the entire host.  Privilege escalation and information
leaks cannot be ruled out.

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

Xen versions 4.12 and onwards are vulnerable.  Xen versions 4.11 and
earlier are not vulnerable.

Only Arm systems are affected.  x86 systems are not affected.

MITIGATION
==========

There is no known mitigation.

CREDITS
=======

This issue was discovered by Jan Beulich of SUSE.

RESOLUTION
==========

Applying the appropriate set of attached patches 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.

xsa473-?.patch           xen-unstable - Xen 4.19.x
xsa473-4.18-?.patch      Xen 4.18.x - Xen 4.17.x

$ sha256sum xsa473*
e70f71258f1998eddafcdb5f4cb46d98e9dedc529f102b85dfb4e5310faf48eb  xsa473-1.patch
a501bde6ffb7391387cffe74e3eb9bd5c06d70bd7695aa811d42c75d3903fa59  xsa473-2.patch
e8a27f02e57d1a8d956cca9c9ed2db90c328911ff3a9434883baf633a0f3be5c  xsa473-4.18-1.patch
b2f6f4560d6082e0fb040f7352dda8963ab2dce207efce289131c10b69ebf656  xsa473-4.18-2.patch
$

DEPLOYMENT DURING EMBARGO
=========================

Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.

But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).

Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.

(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable.  This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)

For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
  http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----

iQFABAEBCAAqFiEEI+MiLBRfRHX6gGCng/4UyVfoK9kFAmjAFU8MHHBncEB4ZW4u
b3JnAAoJEIP+FMlX6CvZ/k0IAMjOW7n+dt0rgaRfwA7twgv8OLLOkuw/+DcPYuR0
tm43Y/5OtqThqmtVqOYdZNA91EQ2rIdh2hkhrCcLI1wrm6qWHvWw4ZUp5VMLyLka
u616++Uk3vlc3BrfVEVXzWgGOGYW1o7KP5njiTGcEMR/3BYC3bYBbrf7PHoDgSUR
xCmHB/tMCZ/XNkYly1oZntlQTyDjW4lnMJJMTJGXqVOviXmpGs52PRsiClk5kUuB
HU8wPkjpw2VQR43iJQWkLQykHnTGWWW/V271br1cJVDHylKaAxETBDUu44JkXTHx
voqmAG9cwm6K5Rlh6junqnfW6+UOe6Ib+FGmRXcBZ8zRAV4=
=Mloq
-----END PGP SIGNATURE-----
From: Jan Beulich <jbeulich@suse.com>
Subject: Arm: foreign page handling in p2m_get_page_from_gfn()

I can't see what would make the 1st of the assertions safe: For example,
the P2M lock not being held, the foreign page may disappear before we
get to call page_get_owner_and_reference(), which hence may return NULL.

Even the 2nd, which appears to be safe safe, is lacking proper release
build fallbacks.

Drop the former in favor of an if(), and convert the latter to the
equivalent of what x86 uses: ASSERT_UNREACHABLE() plus putting of the
obtained page.

This is CVE-2025-58144 / part of XSA-473.

Fixes: 9486a8d07ba8 ("xen/arm: Handle remove foreign mapping")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>

--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -74,10 +74,16 @@ struct page_info *p2m_get_page_from_gfn(
      */
     if ( p2m_is_foreign(p2mt) )
     {
-        struct domain *fdom = page_get_owner_and_reference(page);
-        ASSERT(fdom != NULL);
-        ASSERT(fdom != d);
-        return page;
+        const struct domain *fdom = page_get_owner_and_reference(page);
+
+        if ( fdom )
+        {
+            if ( fdom != d )
+                return page;
+            ASSERT_UNREACHABLE();
+            put_page(page);
+        }
+        return NULL;
     }
 
     return get_page(page, d) ? page : NULL;
From: Jan Beulich <jbeulich@suse.com>
Subject: Arm: adjust locking in p2m_get_page_from_gfn()

In order to safely acquire a reference for a foreign page mapping, the
P2M lock needs to be held until we have the reference in hand (or
getting one failed). Otherwise the page can change P2M type and
ownership in between.

This is CVE-2025-58145 / part of XSA-473.

Fixes: 9486a8d07ba8 ("xen/arm: Handle remove foreign mapping")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>

--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -53,18 +53,22 @@ mfn_t p2m_lookup(struct domain *d, gfn_t
 struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn,
                                         p2m_type_t *t)
 {
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page;
     p2m_type_t p2mt;
-    mfn_t mfn = p2m_lookup(d, gfn, &p2mt);
+    mfn_t mfn;
+
+    p2m_read_lock(p2m);
+    mfn = p2m_get_entry(p2m, gfn, &p2mt, NULL, NULL, NULL);
 
     if ( t )
         *t = p2mt;
 
-    if ( !p2m_is_any_ram(p2mt) )
-        return NULL;
-
-    if ( !mfn_valid(mfn) )
+    if ( !p2m_is_any_ram(p2mt) || !mfn_valid(mfn) )
+    {
+        p2m_read_unlock(p2m);
         return NULL;
+    }
 
     page = mfn_to_page(mfn);
 
@@ -76,6 +80,8 @@ struct page_info *p2m_get_page_from_gfn(
     {
         const struct domain *fdom = page_get_owner_and_reference(page);
 
+        p2m_read_unlock(p2m);
+
         if ( fdom )
         {
             if ( fdom != d )
@@ -86,6 +92,8 @@ struct page_info *p2m_get_page_from_gfn(
         return NULL;
     }
 
+    p2m_read_unlock(p2m);
+
     return get_page(page, d) ? page : NULL;
 }
 
From: Jan Beulich <jbeulich@suse.com>
Subject: Arm: foreign page handling in p2m_get_page_from_gfn()

I can't see what would make the 1st of the assertions safe: For example,
the P2M lock not being held, the foreign page may disappear before we
get to call page_get_owner_and_reference(), which hence may return NULL.

Even the 2nd, which appears to be safe safe, is lacking proper release
build fallbacks.

Drop the former in favor of an if(), and convert the latter to the
equivalent of what x86 uses: ASSERT_UNREACHABLE() plus putting of the
obtained page.

This is CVE-2025-58144 / part of XSA-473.

Fixes: 9486a8d07ba8 ("xen/arm: Handle remove foreign mapping")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>

--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -612,10 +612,16 @@ struct page_info *p2m_get_page_from_gfn(
      */
     if ( p2m_is_foreign(p2mt) )
     {
-        struct domain *fdom = page_get_owner_and_reference(page);
-        ASSERT(fdom != NULL);
-        ASSERT(fdom != d);
-        return page;
+        const struct domain *fdom = page_get_owner_and_reference(page);
+
+        if ( fdom )
+        {
+            if ( fdom != d )
+                return page;
+            ASSERT_UNREACHABLE();
+            put_page(page);
+        }
+        return NULL;
     }
 
     return get_page(page, d) ? page : NULL;
From: Jan Beulich <jbeulich@suse.com>
Subject: Arm: adjust locking in p2m_get_page_from_gfn()

In order to safely acquire a reference for a foreign page mapping, the
P2M lock needs to be held until we have the reference in hand (or
getting one failed). Otherwise the page can change P2M type and
ownership in between.

This is CVE-2025-58145 / part of XSA-473.

Fixes: 9486a8d07ba8 ("xen/arm: Handle remove foreign mapping")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>

--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -591,18 +591,22 @@ mfn_t p2m_lookup(struct domain *d, gfn_t
 struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn,
                                         p2m_type_t *t)
 {
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page;
     p2m_type_t p2mt;
-    mfn_t mfn = p2m_lookup(d, gfn, &p2mt);
+    mfn_t mfn;
+
+    p2m_read_lock(p2m);
+    mfn = p2m_get_entry(p2m, gfn, &p2mt, NULL, NULL, NULL);
 
     if ( t )
         *t = p2mt;
 
-    if ( !p2m_is_any_ram(p2mt) )
-        return NULL;
-
-    if ( !mfn_valid(mfn) )
+    if ( !p2m_is_any_ram(p2mt) || !mfn_valid(mfn) )
+    {
+        p2m_read_unlock(p2m);
         return NULL;
+    }
 
     page = mfn_to_page(mfn);
 
@@ -614,6 +618,8 @@ struct page_info *p2m_get_page_from_gfn(
     {
         const struct domain *fdom = page_get_owner_and_reference(page);
 
+        p2m_read_unlock(p2m);
+
         if ( fdom )
         {
             if ( fdom != d )
@@ -624,6 +630,8 @@ struct page_info *p2m_get_page_from_gfn(
         return NULL;
     }
 
+    p2m_read_unlock(p2m);
+
     return get_page(page, d) ? page : NULL;
 }