mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:615897bc6c("xen/arm: Allow a privileged domain to map foreign page from DOMID_XEN") Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> Reviewed-by: Michal Orzel <michal.orzel@amd.com> Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> (cherry picked from commitf795a9c491)
This commit is contained in:
1 parent
d5ad2233bb
commit
ade0c35777
1 file changed
+16
-11
+16
-11
@@ -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:
|
||||
|
||||