[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git-commits-head
Subject:    KVM: VMX: Don't fudge CR0 and CR4 for restricted L2 guest
From:       Linux Kernel Mailing List <linux-kernel () vger ! kernel ! org>
Date:       2023-07-30 19:44:11
Message-ID: git-mailbomb-linux-master-c4abd7352023aa96114915a0bb2b88016a425cda () kernel ! org
[Download RAW message or body]

Commit:     c4abd7352023aa96114915a0bb2b88016a425cda
Parent:     26a0652cb453c72f6aab0974bc4939e9b14f886b
Refname:    refs/heads/master
Web:        https://git.kernel.org/torvalds/c/c4abd7352023aa96114915a0bb2b88016a425cda
                
Author:     Sean Christopherson <seanjc@google.com>
AuthorDate: Tue Jun 13 13:30:36 2023 -0700
Committer:  Paolo Bonzini <pbonzini@redhat.com>
CommitDate: Sat Jul 29 11:05:32 2023 -0400

    KVM: VMX: Don't fudge CR0 and CR4 for restricted L2 guest
    
    Stuff CR0 and/or CR4 to be compliant with a restricted guest if and only
    if KVM itself is not configured to utilize unrestricted guests, i.e. don't
    stuff CR0/CR4 for a restricted L2 that is running as the guest of an
    unrestricted L1.  Any attempt to VM-Enter a restricted guest with invalid
    CR0/CR4 values should fail, i.e. in a nested scenario, KVM (as L0) should
    never observe a restricted L2 with incompatible CR0/CR4, since nested
    VM-Enter from L1 should have failed.
    
    And if KVM does observe an active, restricted L2 with incompatible state,
    e.g. due to a KVM bug, fudging CR0/CR4 instead of letting VM-Enter fail
    does more harm than good, as KVM will often neglect to undo the side
    effects, e.g. won't clear rmode.vm86_active on nested VM-Exit, and thus
    the damage can easily spill over to L1.  On the other hand, letting
    VM-Enter fail due to bad guest state is more likely to contain the damage
    to L2 as KVM relies on hardware to perform most guest state consistency
    checks, i.e. KVM needs to be able to reflect a failed nested VM-Enter into
    L1 irrespective of (un)restricted guest behavior.
    
    Cc: Jim Mattson <jmattson@google.com>
    Cc: stable@vger.kernel.org
    Fixes: bddd82d19e2e ("KVM: nVMX: KVM needs to unset "unrestricted guest" \
VM-execution control in vmcs02 if vmcs12 doesn't set it")  Signed-off-by: Sean \
Christopherson <seanjc@google.com>  Message-Id: \
<20230613203037.1968489-3-seanjc@google.com>  Signed-off-by: Paolo Bonzini \
                <pbonzini@redhat.com>
---
 arch/x86/kvm/vmx/vmx.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 3d011d62d9696..df461f387e20d 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1513,6 +1513,11 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long \
rflags)  struct vcpu_vmx *vmx = to_vmx(vcpu);
 	unsigned long old_rflags;
 
+	/*
+	 * Unlike CR0 and CR4, RFLAGS handling requires checking if the vCPU
+	 * is an unrestricted guest in order to mark L2 as needing emulation
+	 * if L1 runs L2 as a restricted guest.
+	 */
 	if (is_unrestricted_guest(vcpu)) {
 		kvm_register_mark_available(vcpu, VCPU_EXREG_RFLAGS);
 		vmx->rflags = rflags;
@@ -3265,7 +3270,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 	old_cr0_pg = kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 
 	hw_cr0 = (cr0 & ~KVM_VM_CR0_ALWAYS_OFF);
-	if (is_unrestricted_guest(vcpu))
+	if (enable_unrestricted_guest)
 		hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
 	else {
 		hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
@@ -3293,7 +3298,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 	}
 #endif
 
-	if (enable_ept && !is_unrestricted_guest(vcpu)) {
+	if (enable_ept && !enable_unrestricted_guest) {
 		/*
 		 * Ensure KVM has an up-to-date snapshot of the guest's CR3.  If
 		 * the below code _enables_ CR3 exiting, vmx_cache_reg() will
@@ -3424,7 +3429,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	 * this bit, even if host CR4.MCE == 0.
 	 */
 	hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
-	if (is_unrestricted_guest(vcpu))
+	if (enable_unrestricted_guest)
 		hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
 	else if (vmx->rmode.vm86_active)
 		hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON;
@@ -3444,7 +3449,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	vcpu->arch.cr4 = cr4;
 	kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
 
-	if (!is_unrestricted_guest(vcpu)) {
+	if (!enable_unrestricted_guest) {
 		if (enable_ept) {
 			if (!is_paging(vcpu)) {
 				hw_cr4 &= ~X86_CR4_PAE;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic