From: Nuno Das Neves <[email protected]> Sent: Thursday, 
November 6, 2025 2:14 PM
> 
> 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 <[email protected]>
> Closes: 
> https://lore.kernel.org/linux-hyperv/sn6pr02mb41575be0406d3ab22e1d7db5d4...@sn6pr02mb4157.namprd02.prod.outlook.com/
> Signed-off-by: Nuno Das Neves <[email protected]>
> ---
>  drivers/hv/mshv_root_main.c | 31 +++++++++++--------------------
>  1 file changed, 11 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index 814465a0912d..25a68912a78d 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -1206,21 +1206,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
> @@ -1230,15 +1215,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)
> --
> 2.34.1

Reviewed-by: Michael Kelley <[email protected]>


Reply via email to