From 842d02fdd9d4308fb7108a65cb5b10583f46d22e Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Fri, 24 Apr 2026 14:49:33 -0700 Subject: [PATCH] hypervisor: mshv: Validate GPA mapping with GvaGpaValid flag The GvaGpaValid flag in the intercept message indicates whether the provided GPA corresponds to the decoded GVA. Without checking this flag, the emulator may incorrectly use a stale GPA mapping when the hypervisor invalidates it. Add a check for the GvaGpaValid flag before using the cached (GVA, GPA) mapping. If the flag is clear, use a sentinel value to force translate() to perform a proper hypercall-based translation instead of using an invalid cached mapping. Signed-off-by: Pedro Barbuda Signed-off-by: Muminul Islam --- hypervisor/src/mshv/mod.rs | 21 +++++++++++++++++++-- hypervisor/src/mshv/x86_64/emulator.rs | 7 ++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index a61f2e44e..32ef68bc5 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -720,11 +720,28 @@ impl cpu::Vcpu for MshvVcpu { let gva = info.guest_virtual_address; let gpa = info.guest_physical_address; - debug!("Exit ({msg_type:?}) GVA {gva:x} GPA {gpa:x}"); + // The GvaGpaValid flag indicates that the GPA in the intercept + // message corresponds to the GVA in the message. If that flag + // is set, and the GVA in the message matches the GVA in the decoded + // instruction, then the emulator can use the GPA provided by + // the hypervisor. Otherwise, the emulator must translate the GVA + // via a hypercall. + // SAFETY: accessing the bitfield union variant. + let gva_gpa_valid = + unsafe { info.memory_access_info.__bindgen_anon_1.gva_gpa_valid() != 0 }; + + debug!( + "Exit ({msg_type:?}) GVA {gva:x} GPA {gpa:x} \ + gva_gpa_valid={gva_gpa_valid}" + ); let mut context = MshvEmulatorContext { vcpu: self, - map: (gva, gpa), + map: if gva_gpa_valid { + (gva, gpa) + } else { + (u64::MAX, 0) + }, }; let old_state = context diff --git a/hypervisor/src/mshv/x86_64/emulator.rs b/hypervisor/src/mshv/x86_64/emulator.rs index d668dedde..eb2be3d2f 100644 --- a/hypervisor/src/mshv/x86_64/emulator.rs +++ b/hypervisor/src/mshv/x86_64/emulator.rs @@ -19,7 +19,12 @@ pub struct MshvEmulatorContext<'a> { } impl MshvEmulatorContext<'_> { - // Do the actual gva -> gpa translation + // Do the actual gva -> gpa translation. + // + // When the hypervisor sets GvaGpaValid in the intercept message, `map` + // caches the (gva, gpa) pair as a fast path that avoids a translate + // hypercall. When the flag is clear, `map` is set to a sentinel + // (u64::MAX, 0) so this shortcut never fires. #[allow(non_upper_case_globals)] fn translate(&self, gva: u64, flags: u32) -> Result { if self.map.0 == gva {