From 4608de134f4ea66dedca0aac3be9c33689ca72b9 Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Wed, 29 Apr 2026 15:35:04 -0700 Subject: [PATCH] vmm: igvm: gate CPUID page read with runtime hypervisor check The SnpCpuidInfo allocation and guest_memory.read() call in the isolated page import loop are only needed for KVM's CPUID page retry logic. However, when building with both 'mshv' and 'kvm' features, #[cfg(feature = "kvm")] alone is insufficient as a guard because both features compile into the same binary. Without a runtime hypervisor type check, this code executes on MSHV as well, reading guest memory at arbitrary GPAs that may not be valid in the MSHV memory layout. This can cause undefined behavior or crashes during IGVM loading. Add #[cfg(feature = "kvm")] to the variable declarations and wrap the guest_memory.read() call in a runtime check for HypervisorType::Kvm to ensure it only executes on KVM. Assisted-by: Claude:Opus-4.6 Signed-off-by: Muminul Islam --- vmm/src/igvm/igvm_loader.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/vmm/src/igvm/igvm_loader.rs b/vmm/src/igvm/igvm_loader.rs index 790d04d4f..75b70bb7f 100644 --- a/vmm/src/igvm/igvm_loader.rs +++ b/vmm/src/igvm/igvm_loader.rs @@ -23,12 +23,14 @@ use log::info; #[cfg(feature = "mshv")] use mshv_bindings::*; use thiserror::Error; +#[cfg(all(feature = "kvm", feature = "sev_snp"))] +use vm_memory::Bytes; #[cfg(feature = "sev_snp")] -use vm_memory::{Bytes, GuestAddress, GuestAddressSpace, GuestMemory}; +use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory}; #[cfg(all(feature = "kvm", feature = "sev_snp"))] use vm_migration::Snapshottable; use zerocopy::IntoBytes; -#[cfg(feature = "sev_snp")] +#[cfg(all(feature = "kvm", feature = "sev_snp"))] use zerocopy::{FromBytes, FromZeros}; #[cfg(feature = "sev_snp")] @@ -40,11 +42,11 @@ use crate::memory_manager::{Error as MemoryManagerError, MemoryManager}; #[cfg(feature = "sev_snp")] const ISOLATED_PAGE_SHIFT: u32 = 12; -#[cfg(feature = "sev_snp")] +#[cfg(all(feature = "kvm", feature = "sev_snp"))] const SNP_CPUID_LIMIT: u32 = 64; // see section 7.1 // https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56860.pdf -#[cfg(feature = "sev_snp")] +#[cfg(all(feature = "kvm", feature = "sev_snp"))] #[repr(C)] #[derive(Debug, Clone, PartialEq, Eq, IntoBytes, FromBytes)] pub struct SnpCpuidFunc { @@ -59,7 +61,7 @@ pub struct SnpCpuidFunc { pub reserved: u64, } -#[cfg(feature = "sev_snp")] +#[cfg(all(feature = "kvm", feature = "sev_snp"))] #[repr(C)] #[derive(Debug, Clone, FromBytes, IntoBytes)] pub struct SnpCpuidInfo { @@ -656,8 +658,12 @@ pub fn load_igvm( .collect(); #[cfg(feature = "kvm")] let page_type = group[0].page_type; + #[cfg(feature = "kvm")] let mut new_cp = SnpCpuidInfo::new_zeroed(); - let _ = guest_memory.read(new_cp.as_mut_bytes(), GuestAddress(group[0].gpa)); + #[cfg(feature = "kvm")] + if hypervisor_type == HypervisorType::Kvm { + let _ = guest_memory.read(new_cp.as_mut_bytes(), GuestAddress(group[0].gpa)); + } let import_result = memory_manager .lock() .unwrap()