mshv_partition_create_region() checks for overlapping guest memory
regions using arithmetic that can overflow u64:

  mem->guest_pfn + nr_pages <= rg->start_gfn

If guest_pfn is near U64_MAX, the addition wraps around to a small
value, causing the overlap check to incorrectly pass. This could allow
creation of overlapping regions.

Fix by validating the sum with check_add_overflow() before the loop and
using the pre-computed end_gfn in the comparison.

Fixes: f91bc8f61abf ("mshv: Allow mappings that overlap in uaddr")
Signed-off-by: Stanislav Kinsburskii <[email protected]>
---
 drivers/hv/mshv_root_main.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index aa0f452aa17c1..2b7d56e108bad 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1290,11 +1290,15 @@ static int mshv_partition_create_region(struct 
mshv_partition *partition,
 {
        struct mshv_mem_region *rg;
        u64 nr_pages = HVPFN_DOWN(mem->size);
+       u64 end_gfn;
+
+       if (check_add_overflow(mem->guest_pfn, nr_pages, &end_gfn))
+               return -EINVAL;
 
        /* Reject overlapping regions */
        spin_lock(&partition->pt_mem_regions_lock);
        hlist_for_each_entry(rg, &partition->pt_mem_regions, hnode) {
-               if (mem->guest_pfn + nr_pages <= rg->start_gfn ||
+               if (end_gfn <= rg->start_gfn ||
                    rg->start_gfn + rg->nr_pages <= mem->guest_pfn)
                        continue;
                spin_unlock(&partition->pt_mem_regions_lock);



Reply via email to