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;
 }
 
