Skip to content

Commit ba9eb9b

Browse files
NunoDasNevesliuw
authored andcommitted
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: 621191d ("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>
1 parent 8ec6070 commit ba9eb9b

1 file changed

Lines changed: 11 additions & 20 deletions

File tree

drivers/hv/mshv_root_main.c

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,21 +1174,6 @@ mshv_partition_region_by_gfn(struct mshv_partition *partition, u64 gfn)
11741174
return NULL;
11751175
}
11761176

1177-
static struct mshv_mem_region *
1178-
mshv_partition_region_by_uaddr(struct mshv_partition *partition, u64 uaddr)
1179-
{
1180-
struct mshv_mem_region *region;
1181-
1182-
hlist_for_each_entry(region, &partition->pt_mem_regions, hnode) {
1183-
if (uaddr >= region->start_uaddr &&
1184-
uaddr < region->start_uaddr +
1185-
(region->nr_pages << HV_HYP_PAGE_SHIFT))
1186-
return region;
1187-
}
1188-
1189-
return NULL;
1190-
}
1191-
11921177
/*
11931178
* NB: caller checks and makes sure mem->size is page aligned
11941179
* Returns: 0 with regionpp updated on success, or -errno
@@ -1198,15 +1183,21 @@ static int mshv_partition_create_region(struct mshv_partition *partition,
11981183
struct mshv_mem_region **regionpp,
11991184
bool is_mmio)
12001185
{
1201-
struct mshv_mem_region *region;
1186+
struct mshv_mem_region *region, *rg;
12021187
u64 nr_pages = HVPFN_DOWN(mem->size);
12031188

12041189
/* Reject overlapping regions */
1205-
if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) ||
1206-
mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) ||
1207-
mshv_partition_region_by_uaddr(partition, mem->userspace_addr) ||
1208-
mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1))
1190+
hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) {
1191+
u64 rg_size = rg->nr_pages << HV_HYP_PAGE_SHIFT;
1192+
1193+
if ((mem->guest_pfn + nr_pages <= rg->start_gfn ||
1194+
rg->start_gfn + rg->nr_pages <= mem->guest_pfn) &&
1195+
(mem->userspace_addr + mem->size <= rg->start_uaddr ||
1196+
rg->start_uaddr + rg_size <= mem->userspace_addr))
1197+
continue;
1198+
12091199
return -EEXIST;
1200+
}
12101201

12111202
region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages);
12121203
if (!region)

0 commit comments

Comments
 (0)