mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
mshv: Fix create memory region overlap check
The current check is incorrect; it only checks if the beginning or end
of a region is within an existing region. This doesn't account for
userspace specifying a region that begins before and ends after an
existing region.
Change the logic to a range intersection check against gfns and uaddrs
for each region.
Remove mshv_partition_region_by_uaddr() as it is no longer used.
Fixes: 621191d709 ("Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs")
Reported-by: Michael Kelley <mhklinux@outlook.com>
Closes: https://lore.kernel.org/linux-hyperv/SN6PR02MB41575BE0406D3AB22E1D7DB5D4C2A@SN6PR02MB4157.namprd02.prod.outlook.com/
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
This commit is contained in:
parent
8ec6070fc8
commit
ba9eb9b86d
|
|
@ -1174,21 +1174,6 @@ mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct mshv_mem_region *
|
||||
mshv_partition_region_by_uaddr(struct mshv_partition *partition, u64 uaddr)
|
||||
{
|
||||
struct mshv_mem_region *region;
|
||||
|
||||
hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) {
|
||||
if (uaddr >= region->start_uaddr &&
|
||||
uaddr < region->start_uaddr +
|
||||
(region->nr_pages << HV_HYP_PAGE_SHIFT))
|
||||
return region;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: caller checks and makes sure mem->size is page aligned
|
||||
* Returns: 0 with regionpp updated on success, or -errno
|
||||
|
|
@ -1198,15 +1183,21 @@ static int mshv_partition_create_region(struct mshv_partition *partition,
|
|||
struct mshv_mem_region **regionpp,
|
||||
bool is_mmio)
|
||||
{
|
||||
struct mshv_mem_region *region;
|
||||
struct mshv_mem_region *region, *rg;
|
||||
u64 nr_pages = HVPFN_DOWN(mem->size);
|
||||
|
||||
/* Reject overlapping regions */
|
||||
if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) ||
|
||||
mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) ||
|
||||
mshv_partition_region_by_uaddr(partition, mem->userspace_addr) ||
|
||||
mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1))
|
||||
hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) {
|
||||
u64 rg_size = rg->nr_pages << HV_HYP_PAGE_SHIFT;
|
||||
|
||||
if ((mem->guest_pfn + nr_pages <= rg->start_gfn ||
|
||||
rg->start_gfn + rg->nr_pages <= mem->guest_pfn) &&
|
||||
(mem->userspace_addr + mem->size <= rg->start_uaddr ||
|
||||
rg->start_uaddr + rg_size <= mem->userspace_addr))
|
||||
continue;
|
||||
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages);
|
||||
if (!region)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user