Skip to content

Commit 1dc35da

Browse files
ladiprobonzini
authored andcommitted
KVM: nVMX: check host CR3 on vmentry and vmexit
This commit adds missing host CR3 checks. Before entering guest mode, the value of CR3 is checked for reserved bits. After returning, nested_vmx_load_cr3 is called to set the new CR3 value and check and load PDPTRs. Signed-off-by: Ladi Prosek <[email protected]> Signed-off-by: Radim Krčmář <[email protected]>
1 parent 9ed38ff commit 1dc35da

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

arch/x86/include/uapi/asm/vmx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
{ EXIT_REASON_XRSTORS, "XRSTORS" }
134134

135135
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
136+
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
136137
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
137138

138139
#endif /* _UAPIVMX_H */

arch/x86/kvm/vmx.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9968,6 +9968,14 @@ static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
99689968
return 0;
99699969
}
99709970

9971+
static bool nested_cr3_valid(struct kvm_vcpu *vcpu, unsigned long val)
9972+
{
9973+
unsigned long invalid_mask;
9974+
9975+
invalid_mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
9976+
return (val & invalid_mask) == 0;
9977+
}
9978+
99719979
/*
99729980
* Load guest's/host's cr3 at nested entry/exit. nested_ept is true if we are
99739981
* emulating VM entry into a guest with EPT enabled.
@@ -9977,11 +9985,8 @@ static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
99779985
static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
99789986
unsigned long *entry_failure_code)
99799987
{
9980-
unsigned long invalid_mask;
9981-
99829988
if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
9983-
invalid_mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
9984-
if (cr3 & invalid_mask) {
9989+
if (!nested_cr3_valid(vcpu, cr3)) {
99859990
*entry_failure_code = ENTRY_FAIL_DEFAULT;
99869991
return 1;
99879992
}
@@ -10452,7 +10457,8 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
1045210457
}
1045310458

1045410459
if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
10455-
!nested_host_cr4_valid(vcpu, vmcs12->host_cr4)) {
10460+
!nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
10461+
!nested_cr3_valid(vcpu, vmcs12->host_cr3)) {
1045610462
nested_vmx_failValid(vcpu,
1045710463
VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
1045810464
goto out;
@@ -10879,6 +10885,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
1087910885
struct vmcs12 *vmcs12)
1088010886
{
1088110887
struct kvm_segment seg;
10888+
unsigned long entry_failure_code;
1088210889

1088310890
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
1088410891
vcpu->arch.efer = vmcs12->host_ia32_efer;
@@ -10916,8 +10923,12 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
1091610923

1091710924
nested_ept_uninit_mmu_context(vcpu);
1091810925

10919-
kvm_set_cr3(vcpu, vmcs12->host_cr3);
10920-
kvm_mmu_reset_context(vcpu);
10926+
/*
10927+
* Only PDPTE load can fail as the value of cr3 was checked on entry and
10928+
* couldn't have changed.
10929+
*/
10930+
if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
10931+
nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
1092110932

1092210933
if (!enable_ept)
1092310934
vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;

0 commit comments

Comments
 (0)