Skip to content

Commit 2e7eab8

Browse files
jsmattsonjrsean-jc
authored andcommitted
KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS
According to Intel's document on Indirect Branch Restricted Speculation, "Enabling IBRS does not prevent software from controlling the predicted targets of indirect branches of unrelated software executed later at the same predictor mode (for example, between two different user applications, or two different virtual machines). Such isolation can be ensured through use of the Indirect Branch Predictor Barrier (IBPB) command." This applies to both basic and enhanced IBRS. Since L1 and L2 VMs share hardware predictor modes (guest-user and guest-kernel), hardware IBRS is not sufficient to virtualize IBRS. (The way that basic IBRS is implemented on pre-eIBRS parts, hardware IBRS is actually sufficient in practice, even though it isn't sufficient architecturally.) For virtual CPUs that support IBRS, add an indirect branch prediction barrier on emulated VM-exit, to ensure that the predicted targets of indirect branches executed in L1 cannot be controlled by software that was executed in L2. Since we typically don't intercept guest writes to IA32_SPEC_CTRL, perform the IBPB at emulated VM-exit regardless of the current IA32_SPEC_CTRL.IBRS value, even though the IBPB could technically be deferred until L1 sets IA32_SPEC_CTRL.IBRS, if IA32_SPEC_CTRL.IBRS is clear at emulated VM-exit. This is CVE-2022-2196. Fixes: 5c911be ("KVM: nVMX: Skip IBPB when switching between vmcs01 and vmcs02") Cc: Sean Christopherson <seanjc@google.com> Signed-off-by: Jim Mattson <jmattson@google.com> Reviewed-by: Sean Christopherson <seanjc@google.com> Link: https://lore.kernel.org/r/20221019213620.1953281-3-jmattson@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 4f20998 commit 2e7eab8

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

arch/x86/kvm/vmx/nested.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4798,6 +4798,17 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
47984798

47994799
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
48004800

4801+
/*
4802+
* If IBRS is advertised to the vCPU, KVM must flush the indirect
4803+
* branch predictors when transitioning from L2 to L1, as L1 expects
4804+
* hardware (KVM in this case) to provide separate predictor modes.
4805+
* Bare metal isolates VMX root (host) from VMX non-root (guest), but
4806+
* doesn't isolate different VMCSs, i.e. in this case, doesn't provide
4807+
* separate modes for L2 vs L1.
4808+
*/
4809+
if (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
4810+
indirect_branch_prediction_barrier();
4811+
48014812
/* Update any VMCS fields that might have changed while L2 ran */
48024813
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
48034814
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);

arch/x86/kvm/vmx/vmx.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,8 +1348,10 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
13481348

13491349
/*
13501350
* No indirect branch prediction barrier needed when switching
1351-
* the active VMCS within a guest, e.g. on nested VM-Enter.
1352-
* The L1 VMM can protect itself with retpolines, IBPB or IBRS.
1351+
* the active VMCS within a vCPU, unless IBRS is advertised to
1352+
* the vCPU. To minimize the number of IBPBs executed, KVM
1353+
* performs IBPB on nested VM-Exit (a single nested transition
1354+
* may switch the active VMCS multiple times).
13531355
*/
13541356
if (!buddy || WARN_ON_ONCE(buddy->vmcs != prev))
13551357
indirect_branch_prediction_barrier();

0 commit comments

Comments
 (0)