From ade0c357771e1eccc08c0c459d23fb19ff4933a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Tue, 14 Jul 2026 19:16:56 +0000 Subject: [PATCH] xen/arm: Reject pseudo-domain foreign mappings in xenmem_add_to_physmap_one() A privileged domain on Arm64 can trigger a data abort in the hypervisor by issuing memory_op's XENMEM_add_to_physmap_batch sub-op with space=XENMAPSPACE_gmfn_foreign, idx=0 and foreign_domid=DOMID_IO. get_pg_owner(DOMID_IO) succeeds, returning a pointer to the dom_io pseudo-domain. The subsequent get_page_from_gfn(dom_io, ...) then attempts to walk dom_io's P2M table, which is not initialized for pseudo-domains, resulting in a data abort in p2m_get_entry() when it dereferences the invalid pointer returned by p2m_get_root_pointer(). Replace get_pg_owner() with explicit domain lookup logic matching the x86 implementation: handle DOMID_XEN via rcu_lock_domain(dom_xen), and resolve all other domain IDs via rcu_lock_remote_domain_by_id(), which rejects pseudo-domains (DOMID_IO, etc.) that are not present in the domain hash, returning -ESRCH before any P2M access occurs. Fixes: 615897bc6c01 ("xen/arm: Allow a privileged domain to map foreign page from DOMID_XEN") Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Michal Orzel Release-Acked-by: Oleksii Kurochko (cherry picked from commit f795a9c491a704b6cd6ca0381b033e6beb692cb3) --- xen/arch/arm/mm.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 9281dc8330..a60a9e6f4a 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -149,20 +149,25 @@ int xenmem_add_to_physmap_one( struct domain *od; p2m_type_t p2mt; - od = get_pg_owner(extra.foreign_domid); - if ( od == NULL ) - return -ESRCH; - - if ( od == d ) + if ( extra.foreign_domid == DOMID_XEN ) + od = rcu_lock_domain(dom_xen); + else { - put_pg_owner(od); - return -EINVAL; + rc = rcu_lock_remote_domain_by_id(extra.foreign_domid, &od); + if ( rc ) + return rc; + + if ( od == d ) + { + rcu_unlock_domain(od); + return -EINVAL; + } } rc = xsm_map_gmfn_foreign(XSM_TARGET, d, od); if ( rc ) { - put_pg_owner(od); + rcu_unlock_domain(od); return rc; } @@ -171,7 +176,7 @@ int xenmem_add_to_physmap_one( page = get_page_from_gfn(od, idx, &p2mt, P2M_ALLOC); if ( !page ) { - put_pg_owner(od); + rcu_unlock_domain(od); return -EINVAL; } @@ -180,13 +185,13 @@ int xenmem_add_to_physmap_one( else { put_page(page); - put_pg_owner(od); + rcu_unlock_domain(od); return -EINVAL; } mfn = page_to_mfn(page); - put_pg_owner(od); + rcu_unlock_domain(od); break; } case XENMAPSPACE_dev_mmio: