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_root_main.c | 3 ++-
drivers/hv/mshv_synic.c | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 2b7d56e108bad..f01bd0877aef1 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 d4d98fa771189..5333b3889a408 100644
--- a/drivers/hv/mshv_synic.c
+++ b/drivers/hv/mshv_synic.c
@@ -244,7 +244,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;
@@ -293,7 +293,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;
@@ -388,7 +388,7 @@ mshv_intercept_isr(struct hv_message *msg)
pr_debug("VP index %u out of bounds\n", vp_index);
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;