According to section "Checks on VMX Controls" in Intel SDM vol 3C, the following check needs to be enforced on vmentry of L2 guests: If the “enable EPT” VM-execution control is 1, the EPTP VM-execution control field must satisfy the following checks: — The EPT memory type (bits 2:0) must be a value supported by the processor as indicated in the IA32_VMX_EPT_VPID_CAP MSR. — Bits 5:3 (1 less than the EPT page-walk length) must be 3, indicating an EPT page-walk length of 4. — Bit 6 (enable bit for accessed and dirty flags for EPT) must be 0 if bit 21 of the IA32_VMX_EPT_VPID_CAP MSR is read as 0, indicating that the processor does not support accessed and dirty flags for EPT. — Reserved bits 11:7 and 63:N (where N is the processor’s physical-address width) must all be 0. Suggested-by: Liran Alon <liran.alon@xxxxxxxxxx> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> Reviewed-by: Darren Kenny <darren.kenny@xxxxxxxxxx> --- arch/x86/include/asm/vmx.h | 4 +++- arch/x86/kvm/vmx.c | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 6aa8499..4e44c58 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -465,7 +465,7 @@ enum vmcs_field { #define VMX_EPT_2MB_PAGE_BIT (1ull << 16) #define VMX_EPT_1GB_PAGE_BIT (1ull << 17) #define VMX_EPT_INVEPT_BIT (1ull << 20) -#define VMX_EPT_AD_BIT (1ull << 21) +#define VMX_EPT_AD_BIT (1ull << 21) #define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25) #define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26) @@ -493,6 +493,8 @@ enum vmcs_field { VMX_EPT_WRITABLE_MASK | \ VMX_EPT_EXECUTABLE_MASK) #define VMX_EPT_MT_MASK (7ull << VMX_EPT_MT_EPTE_SHIFT) +#define VMX_EPTP_RESV_BITS_SHIFT 7 +#define VMX_EPTP_RESV_BITS_MASK 0x1full /* The mask to use to trigger an EPT Misconfiguration in order to track MMIO */ #define VMX_EPT_MISCONFIG_WX_VALUE (VMX_EPT_WRITABLE_MASK | \ diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5d8e317..0df8273 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8708,7 +8708,8 @@ static bool valid_ept_address(struct kvm_vcpu *vcpu, u64 address) return false; /* Reserved bits should not be set */ - if (address >> maxphyaddr || ((address >> 7) & 0x1f)) + if (address >> maxphyaddr || + ((address >> VMX_EPTP_RESV_BITS_SHIFT) & VMX_EPTP_RESV_BITS_MASK)) return false; /* AD, if set, should be supported */ @@ -10602,8 +10603,6 @@ static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu) static int nested_ept_init_mmu_context(struct kvm_vcpu *vcpu) { WARN_ON(mmu_is_nested(vcpu)); - if (!valid_ept_address(vcpu, nested_ept_get_cr3(vcpu))) - return 1; kvm_mmu_unload(vcpu); kvm_init_shadow_ept_mmu(vcpu, @@ -11645,6 +11644,10 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) } } + if (nested_cpu_has_ept(vmcs12) && + !valid_ept_address(vcpu, vmcs12->ept_pointer)) + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu)) return VMXERR_ENTRY_INVALID_CONTROL_FIELD; -- 2.9.5