mshv_intercept_isr() reads vp_index from the intercept message payload
and uses it directly to index into partition->pt_vp_array without
validating it against MSHV_MAX_VPS. A malformed or corrupted hypervisor
message with a vp_index beyond the array bounds would cause an
out-of-bounds memory access in interrupt context, likely crashing the
host.
Use READ_ONCE() when reading vp_index from the shared SynIC message
page to prevent the compiler from re-fetching the value between the
bounds check and the array access.
Both handle_bitset_message() and handle_pair_message() already validate
vp_index before use. Add the same check to mshv_intercept_isr() for
consistency.
Fixes: 621191d709b14 ("Drivers: hv: Introduce mshv_root module to expose
/dev/mshv to VMMs")
Signed-off-by: Stanislav Kinsburskii <[email protected]>
---
drivers/hv/mshv_synic.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
index 43f1bcbbf2d34..d4d98fa771189 100644
--- a/drivers/hv/mshv_synic.c
+++ b/drivers/hv/mshv_synic.c
@@ -382,8 +382,12 @@ mshv_intercept_isr(struct hv_message *msg)
* (because the vp is only deleted when the partition is), no additional
* locking is needed here
*/
- vp_index =
- ((struct hv_opaque_intercept_message *)msg->u.payload)->vp_index;
+ vp_index = READ_ONCE(
+ ((struct hv_opaque_intercept_message
*)msg->u.payload)->vp_index);
+ if (unlikely(vp_index >= MSHV_MAX_VPS)) {
+ pr_debug("VP index %u out of bounds\n", vp_index);
+ goto unlock_out;
+ }
vp = partition->pt_vp_array[vp_index];
if (unlikely(!vp)) {
pr_debug("failed to find VP %u\n", vp_index);