|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [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 <oleksandr_tyshchenko@xxxxxxxx>
---
Discovered while testing boundary conditions. An unprivileged domain
cannot trigger this crash, any attempt to issue the hypercall with
these parameters is blocked by the XSM, resulting in -EPERM.
The following test, when run in a privileged Arm64 domain, reliably
triggers the panic:
void test(void)
{
/*
* Crucial: idx 0 is required to bypass max_mapped_gfn bounds checks
* in p2m_get_entry().
* The P2M walker first performs a bounds check. Because dom_io is not
* fully initialized, its max bounds are 0. A large idx fails the bounds
* check, safely returns error, and aborts before the pointer dereference.
*/
unsigned long idx = 0;
/* Arbitrary target GFN, the hypervisor crashes before mapping occurs */
unsigned long gpfn = 0x100000;
int ret, err = 0;
struct xen_add_to_physmap_batch xatpb = {
.domid = DOMID_SELF,
.space = XENMAPSPACE_gmfn_foreign,
.size = 1,
/*
* Crucial: DOMID_IO lacks a P2M table, causing p2m_get_root_pointer()
* to return an invalid pointer (garbage) in p2m_get_entry()
*/
.u.foreign_domid = DOMID_IO,
.idxs = &idx,
.gpfns = &gpfn,
.errs = &err
};
ret = hypercall_memory_op(XENMEM_add_to_physmap_batch, &xatpb);
if ( ret || err )
{
printk("Test: XENMEM_add_to_physmap_batch failed (ret=%d, err=%d)\n",
ret, err);
}
}
(XEN) Data Abort Trap. Syndrome=0x4
(XEN) Walking Hypervisor VA 0xb6d9100000000000 on CPU0 via TTBR
0x00000000406fb000
(XEN) 0TH[0x020] = 0x0
(XEN) CPU0: Unexpected Trap: Data Abort
(XEN) ----[ Xen-4.23-unstable arm64 debug=n Tainted: I ]----
(XEN) CPU: 0
(XEN) PC: 00000a000024732c p2m.c#p2m_next_level+0x2c/0x258
(XEN) LR: 00000a00002489b0
(XEN) SP: 000080007e1b79f0
(XEN) CPSR: 0000000080000249 MODE:64-bit EL2h (Hypervisor, handler)
(XEN) X0: 000080007ffe5200 X1: 0000000000000001 X2: 0000000000000000
(XEN) X3: 000080007e1b7aa8 X4: 0000000000000000 X5: ffffffffffffffff
(XEN) X6: 00000a000027a000 X7: 0000000000000000 X8: 00000a000027b000
(XEN) X9: 0000000000000000 X10: ffffffffffffffff X11: ffffff8000015ff0
(XEN) X12: ffffff800000a428 X13: 0000000000000006 X14: 0000000000000000
(XEN) X15: 0000000000000000 X16: 000000000000000c X17: 0000000000000000
(XEN) X18: 0000000000000000 X19: 0000000000000000 X20: 0000000000000000
(XEN) X21: 0000000000000000 X22: 000080007e1b7aa8 X23: 000080007e1b7b1c
(XEN) X24: b6d9100000000000 X25: 0000000000000000 X26: b6d9100000000000
(XEN) X27: 0000000000000000 X28: 000080007ffe5200 FP: ffffff8000015fa0
(XEN)
(XEN) VTCR_EL2: 0000000080043594
(XEN) VTTBR_EL2: 00010000bffd2000
(XEN)
(XEN) SCTLR_EL2: 0000000030cd183d
(XEN) HCR_EL2: 00000000807c663f
(XEN) TTBR0_EL2: 00000000406fb000
(XEN)
(XEN) ESR_EL2: 0000000096000004
(XEN) HPFAR_EL2: 0000000000220000
(XEN) FAR_EL2: b6d9100000000000
(XEN)
(XEN) Xen stack trace from sp=000080007e1b79f0:
(XEN) 0000000000000000 0000000000000000 0000000000000000 000080007e1b7ab0
(XEN) 000080007e1b7b1c 0000000000000000 0000000000000000 0000000000000000
(XEN) 0000000000000001 00000a00002489b0 000080007ffe5000 00000a00002e8040
(XEN) 000080007ffd3000 000080007e1b7b84 0000000000000000 000080007ffd3000
(XEN) 00000a00002e9308 0000000000007ff1 0000000000000000 0000000000000000
(XEN) 00000a0000252f1c 00000a0000253a88 0000000000000008 b6d9100000000000
(XEN) 0000000000000000 0000000000000000 000080007ffe5000 ffffffffffffffff
(XEN) 000080007ffd3000 0000000000100000 00000a00002ef9a8 00000a00002efa24
(XEN) 00000a00002e8228 00000a000025247c 00000a00002e8280 ffffff8000015fd0
(XEN) 000080007e1b7c60 0000000000000000 00000a00002e8280 ffffff8000015fd0
(XEN) 000080007e1b7c60 0000000000000000 0000000000000000 000080007ffd3000
(XEN) 00000a00002e9308 0000000000007ff1 0000000000000000 0000000000000000
(XEN) 00000a0000219b5c 00000a00002754d9 0000000000000020 ffffffffffffffff
(XEN) 000080007e1b7ea0 000080007e1bb000 000080007e1b7fa8 0000000040000345
(XEN) 000000005a000ea1 0000000000000000 0000000000000000 0000000000000000
(XEN) 0000000000000000 0000000000000000 00000a00002556c0 000000000000001f
(XEN) 00000a00002eeb00 000080007e1b7c80 0000000000000000 0000000000001fff
(XEN) 0000000093830045 000080007ffd3000 000000000000000a 0000000000000240
(XEN) 00000a000024df08 000080007ffd3500 0000000000000000 000080007ffd3500
(XEN) 000080007e1b7d88 0000000040000249 0000000000000000 00000a000024432c
(XEN) 0000000000000000 0000000000000000 0000000000100000 0000000000000240
(XEN) 0000000000000000 0000000000000000 0000000000000005 0000000000000020
(XEN) 0000000000004000 00000a00002ef000 ffffffffffffffff fefefefefefeff09
(XEN) 7f7f7f7f7f7f7f7f 0101010101010101 0000000000000008 0000000000000006
(XEN) 0000000000000000 0000000000000000 00000a000023cb50 0000000000000000
(XEN) 0000000000000000 0000000000000000 000080007ffd3500 000080007ffd3000
(XEN) 000000000000000a 000080007ffd353c 000080007ffd3000 000000000000000a
(XEN) 0000000000000240 0000000000000000 0000000000000000 ffffff8000015f10
(XEN) 00000a000025e260 000080007e1b7da0 7ff1000100047ff0 ffffff8000015fc0
(XEN) ffffff8000015fc8 ffffff8000015fbc 000080007fffa9c0 00000a000025de70
(XEN) 0000000093830045 000080007e1b7e88 00000a00002e8130 0000000000000000
(XEN) 00000a00002eeb00 00000a00002e9308 0000000000000001 ffffffffffffffff
(XEN) 000080007e1bb000 00000a00002e8280 0000000000000000 0000000000000000
(XEN) 0000000000000000 0000000000000000 00000a0000256ff0 00000a00002e8280
(XEN) 000080007e1bb000 00000a00002e8280 0000000400000004 00000a00002e8280
(XEN) 0000000000000000 00000a0000256fd4 00000a0000258cc8 ffffff800000c000
(XEN) 0000000000000000 0000000043e00000 0000000000000000 0000000043e00000
(XEN) 00000a0000244480 0000000022000000 0000000000000017 ffffff8000015fd0
(XEN) ffffff8000015fbc ffffff8000015fc8 ffffff8000015fc0 7ff1000100047ff0
(XEN) 0000000000100000 ffffff800000a42a 00000000ffffffff 0000000000000069
(XEN) Xen call trace:
(XEN) [<00000a000024732c>] p2m.c#p2m_next_level+0x2c/0x258 (PC)
(XEN) [<00000a00002489b0>] p2m_get_entry+0xd0/0x218 (LR)
(XEN)
(XEN)
(XEN) ****************************************
(XEN) Panic on CPU 0:
(XEN) CPU0: Unexpected Trap: Data Abort
(XEN) ****************************************
(XEN)
(XEN) Reboot in five seconds...
---
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 65aea71c43..751f2f42fb 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -191,20 +191,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;
}
@@ -213,7 +218,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;
}
@@ -222,13 +227,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:
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |