|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XEN PATCH] xen/common: validate shared memory guest address overlap with guest RAM
Currently, process_shm() does not check whether the guest physical
address of a shared memory region overlaps with the domain's allocated RAM
banks.
Neither process_shm() nor p2m_set_entry() checks for existing
mappings, so the RAM mapping is silently overwritten if a user
specifies a guest physical address that falls within the guest RAM
range. Since construct_domain() loads the kernel after process_shm(),
the kernel can end up in shared memory pages. This can cause:
- Another domain corrupting the kernel via shared memory write
- Silent guest crash with no error message from Xen
Add a check in process_shm() to validate that the shared memory
guest address range does not overlap with any of the domain's
allocated RAM banks.
Signed-off-by: Joan Bae <joan.bae@xxxxxxxxxx>
---
xen/common/device-tree/static-shmem.c | 37 +++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/xen/common/device-tree/static-shmem.c
b/xen/common/device-tree/static-shmem.c
index 4c4cc1b123..b0ae0304a1 100644
--- a/xen/common/device-tree/static-shmem.c
+++ b/xen/common/device-tree/static-shmem.c
@@ -293,6 +293,31 @@ static bool __init save_map_heap_pages(struct domain *d,
struct page_info *pg,
return false;
}
+static bool __init
+check_shm_guest_paddr_overlap(struct kernel_info *kinfo, paddr_t gbase,
+ paddr_t size)
+{
+ unsigned int i;
+ const struct membanks *kinfo_mem = kernel_info_get_mem_const(kinfo);
+ paddr_t gend = gbase + size;
+
+ for ( i = 0; i < kinfo_mem->nr_banks; i++ )
+ {
+ paddr_t bankbase = kinfo_mem->bank[i].start;
+ paddr_t bankend = bankbase + kinfo_mem->bank[i].size;
+
+ /* Check if shared memory overlaps with guest RAM */
+ if ( gbase < bankend && bankbase < gend )
+ {
+ printk("Shared memory guest address 0x%"PRIpaddr" - 0x%"PRIpaddr""
+ " overlaps with guest RAM 0x%"PRIpaddr" - 0x%"PRIpaddr"\n",
+ gbase, gend - 1, bankbase, bankend - 1);
+ return true;
+ }
+ }
+
+ return false;
+}
+
int __init process_shm(struct domain *d, struct kernel_info *kinfo,
const struct dt_device_node *node)
{
@@ -355,6 +380,12 @@ int __init process_shm(struct domain *d, struct
kernel_info *kinfo,
/* guest phys address is after host phys address */
gbase = dt_read_paddr(cells + addr_cells, addr_cells);
+ if ( check_shm_guest_paddr_overlap(kinfo, gbase, psize) )
+ {
+ printk("%pd: shared memory region overlaps with the guest's
RAM range\n", d);
+ return -EINVAL;
+ }
+
if ( is_domain_direct_mapped(d) && (pbase != gbase) )
{
printk("%pd: physical address 0x%"PRIpaddr" and guest address
0x%"PRIpaddr" are not direct-mapped.\n",
@@ -396,6 +427,12 @@ int __init process_shm(struct domain *d, struct
kernel_info *kinfo,
/* guest phys address is right at the beginning */
gbase = dt_read_paddr(cells, addr_cells);
+ if ( check_shm_guest_paddr_overlap(kinfo, gbase, psize) )
+ {
+ printk("%pd: shared memory region overlaps with the guest's
RAM range\n", d);
+ return -EINVAL;
+ }
+
if ( !alloc_bank )
{
alloc_heap_pages_cb_extra cb_arg = { d, role_str, gbase,
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |