The bounds check inside the PFN-filling loop can return -EINVAL while
interrupts are disabled via local_irq_save(), leaking IRQ state.

Remove the check — it is redundant because the loop invariant
(done + i < page_count == page_struct_count >> large_shift) guarantees
(done + i) << large_shift < page_struct_count always holds.

While here, fix type mismatches: change 'int done' to 'u64 done' and
use u64 for loop and batch-size variables so they match the u64
page_count they are compared against.

Fixes: 621191d709b14 ("Drivers: hv: Introduce mshv_root module to expose 
/dev/mshv to VMMs")
Signed-off-by: Stanislav Kinsburskii <[email protected]>
---
 drivers/hv/mshv_root_hv_call.c |   18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
index 129456bd72aba..cc580225e9e45 100644
--- a/drivers/hv/mshv_root_hv_call.c
+++ b/drivers/hv/mshv_root_hv_call.c
@@ -1042,7 +1042,7 @@ int hv_call_modify_spa_host_access(u64 partition_id, 
struct page **pages,
 {
        struct hv_input_modify_sparse_spa_page_host_access *input_page;
        u64 status;
-       int done = 0;
+       u64 done = 0;
        unsigned long irq_flags, large_shift = 0;
        u64 page_count = page_struct_count;
        u16 code = acquire ? HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS :
@@ -1059,9 +1059,9 @@ int hv_call_modify_spa_host_access(u64 partition_id, 
struct page **pages,
        }
 
        while (done < page_count) {
-               ulong i, completed, remain = page_count - done;
-               int rep_count = min(remain,
-                                   
HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT);
+               u64 i, completed, remain = page_count - done;
+               u64 rep_count = min_t(u64, remain,
+                                     
HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT);
 
                local_irq_save(irq_flags);
                input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
@@ -1075,15 +1075,9 @@ int hv_call_modify_spa_host_access(u64 partition_id, 
struct page **pages,
                input_page->flags = flags;
                input_page->host_access = host_access;
 
-               for (i = 0; i < rep_count; i++) {
-                       u64 index = (done + i) << large_shift;
-
-                       if (index >= page_struct_count)
-                               return -EINVAL;
-
+               for (i = 0; i < rep_count; i++)
                        input_page->spa_page_list[i] =
-                                               page_to_pfn(pages[index]);
-               }
+                               page_to_pfn(pages[(done + i) << large_shift]);
 
                status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
                                             NULL);



Reply via email to