Commit 112e6601 authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: nVMX: add missing consistency checks for CR0 and CR4

The effective values of the guest CR0 and CR4 registers may differ from
those included in the VMCS12.  In particular, disabling EPT forces
CR4.PAE=1 and disabling unrestricted guest mode forces CR0.PG=CR0.PE=1.

Therefore, checks on these bits cannot be delegated to the processor
and must be performed by KVM.
Reported-by: default avatarReima ISHII <ishiir@g.ecc.u-tokyo.ac.jp>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent bceeedb2
...@@ -3022,7 +3022,7 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, ...@@ -3022,7 +3022,7 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12, struct vmcs12 *vmcs12,
enum vm_entry_failure_code *entry_failure_code) enum vm_entry_failure_code *entry_failure_code)
{ {
bool ia32e; bool ia32e = !!(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE);
*entry_failure_code = ENTRY_FAIL_DEFAULT; *entry_failure_code = ENTRY_FAIL_DEFAULT;
...@@ -3048,6 +3048,13 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, ...@@ -3048,6 +3048,13 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
vmcs12->guest_ia32_perf_global_ctrl))) vmcs12->guest_ia32_perf_global_ctrl)))
return -EINVAL; return -EINVAL;
if (CC((vmcs12->guest_cr0 & (X86_CR0_PG | X86_CR0_PE)) == X86_CR0_PG))
return -EINVAL;
if (CC(ia32e && !(vmcs12->guest_cr4 & X86_CR4_PAE)) ||
CC(ia32e && !(vmcs12->guest_cr0 & X86_CR0_PG)))
return -EINVAL;
/* /*
* If the load IA32_EFER VM-entry control is 1, the following checks * If the load IA32_EFER VM-entry control is 1, the following checks
* are performed on the field for the IA32_EFER MSR: * are performed on the field for the IA32_EFER MSR:
...@@ -3059,7 +3066,6 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, ...@@ -3059,7 +3066,6 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
*/ */
if (to_vmx(vcpu)->nested.nested_run_pending && if (to_vmx(vcpu)->nested.nested_run_pending &&
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) { (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
if (CC(!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer)) || if (CC(!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer)) ||
CC(ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA)) || CC(ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA)) ||
CC(((vmcs12->guest_cr0 & X86_CR0_PG) && CC(((vmcs12->guest_cr0 & X86_CR0_PG) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment