Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 621191d709b1 ("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>

authored by

Nuno Das Neves and committed by
Wei Liu
ba9eb9b8 8ec6070f

+11 -20
+11 -20
drivers/hv/mshv_root_main.c
··· 1174 1174 return NULL; 1175 1175 } 1176 1176 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 - 1192 1177 /* 1193 1178 * NB: caller checks and makes sure mem->size is page aligned 1194 1179 * Returns: 0 with regionpp updated on success, or -errno ··· 1183 1198 struct mshv_mem_region **regionpp, 1184 1199 bool is_mmio) 1185 1200 { 1186 - struct mshv_mem_region *region; 1201 + struct mshv_mem_region *region, *rg; 1187 1202 u64 nr_pages = HVPFN_DOWN(mem->size); 1188 1203 1189 1204 /* Reject overlapping regions */ 1190 - if (mshv_partition_region_by_gfn(partition, mem->guest_pfn) || 1191 - mshv_partition_region_by_gfn(partition, mem->guest_pfn + nr_pages - 1) || 1192 - mshv_partition_region_by_uaddr(partition, mem->userspace_addr) || 1193 - mshv_partition_region_by_uaddr(partition, mem->userspace_addr + mem->size - 1)) 1205 + hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) { 1206 + u64 rg_size = rg->nr_pages << HV_HYP_PAGE_SHIFT; 1207 + 1208 + if ((mem->guest_pfn + nr_pages <= rg->start_gfn || 1209 + rg->start_gfn + rg->nr_pages <= mem->guest_pfn) && 1210 + (mem->userspace_addr + mem->size <= rg->start_uaddr || 1211 + rg->start_uaddr + rg_size <= mem->userspace_addr)) 1212 + continue; 1213 + 1194 1214 return -EEXIST; 1215 + } 1195 1216 1196 1217 region = vzalloc(sizeof(*region) + sizeof(struct page *) * nr_pages); 1197 1218 if (!region)