mshv_vp_create() publishes a VP pointer to pt_vp_array with a plain
store. The ISR reads this array locklessly from interrupt context on
other CPUs. Without memory ordering, a reader may observe the non-NULL
pointer before all VP fields (e.g. vp_register_page, run.vp_suspend_queue)
are fully initialized, leading to use of uninitialized data.

Fix by using smp_store_release() when publishing the VP pointer and
smp_load_acquire() on all lockless ISR read sites. This guarantees that
all VP initialization is visible to readers before the pointer itself.

Fixes: 621191d709b1 ("Drivers: hv: Introduce mshv_root module to expose 
/dev/mshv to VMMs")
Signed-off-by: Stanislav Kinsburskii <[email protected]>
---
 drivers/hv/mshv_eventfd.c   |    2 +-
 drivers/hv/mshv_root_main.c |    3 ++-
 drivers/hv/mshv_synic.c     |    6 +++---
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c
index c99ca5770d3d0..780f0ea43f2c6 100644
--- a/drivers/hv/mshv_eventfd.c
+++ b/drivers/hv/mshv_eventfd.c
@@ -180,7 +180,7 @@ static int mshv_try_assert_irq_fast(struct mshv_irqfd 
*irqfd,
        if (irq->lapic_apic_id >= MSHV_MAX_VPS)
                return -EINVAL;
 
-       vp = partition->pt_vp_array[irq->lapic_apic_id];
+       vp = smp_load_acquire(&partition->pt_vp_array[irq->lapic_apic_id]);
        if (!vp)
                return -EINVAL;
 
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 0e9b696853fcb..4d58e0b005183 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1224,7 +1224,8 @@ mshv_partition_ioctl_create_vp(struct mshv_partition 
*partition,
 
        /* already exclusive with the partition mutex for all ioctls */
        partition->pt_vp_count++;
-       partition->pt_vp_array[args.vp_index] = vp;
+       /* Ensure VP is fully initialized before visible to lockless ISR 
readers */
+       smp_store_release(&partition->pt_vp_array[args.vp_index], vp);
 
        goto out;
 
diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
index 39c6b22e1e11e..a916a39888aad 100644
--- a/drivers/hv/mshv_synic.c
+++ b/drivers/hv/mshv_synic.c
@@ -245,7 +245,7 @@ handle_bitset_message(const struct 
hv_vp_signal_bitset_scheduler_message *msg)
                                goto unlock_out;
                        }
 
-                       vp = partition->pt_vp_array[vp_index];
+                       vp = 
smp_load_acquire(&partition->pt_vp_array[vp_index]);
                        if (unlikely(!vp)) {
                                pr_debug("failed to find VP %u\n", vp_index);
                                goto unlock_out;
@@ -294,7 +294,7 @@ handle_pair_message(const struct 
hv_vp_signal_pair_scheduler_message *msg)
                        break;
                }
 
-               vp = partition->pt_vp_array[vp_index];
+               vp = smp_load_acquire(&partition->pt_vp_array[vp_index]);
                if (!vp) {
                        pr_debug("failed to find VP %u\n", vp_index);
                        break;
@@ -390,7 +390,7 @@ mshv_intercept_isr(struct hv_message *msg)
                goto unlock_out;
        }
        vp_index = array_index_nospec(vp_index, MSHV_MAX_VPS);
-       vp = partition->pt_vp_array[vp_index];
+       vp = smp_load_acquire(&partition->pt_vp_array[vp_index]);
        if (unlikely(!vp)) {
                pr_debug("failed to find VP %u\n", vp_index);
                goto unlock_out;



Reply via email to