Skip to content

Commit d7ddc93

Browse files
pa1guptagregkh
authored andcommitted
x86/vmscape: Add conditional IBPB mitigation
Commit 2f8f173 upstream. VMSCAPE is a vulnerability that exploits insufficient branch predictor isolation between a guest and a userspace hypervisor (like QEMU). Existing mitigations already protect kernel/KVM from a malicious guest. Userspace can additionally be protected by flushing the branch predictors after a VMexit. Since it is the userspace that consumes the poisoned branch predictors, conditionally issue an IBPB after a VMexit and before returning to userspace. Workloads that frequently switch between hypervisor and userspace will incur the most overhead from the new IBPB. This new IBPB is not integrated with the existing IBPB sites. For instance, a task can use the existing speculation control prctl() to get an IBPB at context switch time. With this implementation, the IBPB is doubled up: one at context switch and another before running userspace. The intent is to integrate and optimize these cases post-embargo. [ dhansen: elaborate on suboptimal IBPB solution ] Suggested-by: Dave Hansen <[email protected]> Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Dave Hansen <[email protected]> Reviewed-by: Borislav Petkov (AMD) <[email protected]> Acked-by: Sean Christopherson <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7c62c44 commit d7ddc93

File tree

5 files changed

+27
-0
lines changed

5 files changed

+27
-0
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@
482482
#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */
483483
#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */
484484
#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */
485+
#define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */
485486

486487
/*
487488
* BUG word(s)

arch/x86/include/asm/entry-common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
9292
* 8 (ia32) bits.
9393
*/
9494
choose_random_kstack_offset(rdtsc());
95+
96+
/* Avoid unnecessary reads of 'x86_ibpb_exit_to_user' */
97+
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
98+
this_cpu_read(x86_ibpb_exit_to_user)) {
99+
indirect_branch_prediction_barrier();
100+
this_cpu_write(x86_ibpb_exit_to_user, false);
101+
}
95102
}
96103
#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare
97104

arch/x86/include/asm/nospec-branch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,8 @@ void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
549549

550550
extern u64 x86_pred_cmd;
551551

552+
DECLARE_PER_CPU(bool, x86_ibpb_exit_to_user);
553+
552554
static inline void indirect_branch_prediction_barrier(void)
553555
{
554556
alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB);

arch/x86/kernel/cpu/bugs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
6060
DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
6161
EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current);
6262

63+
/*
64+
* Set when the CPU has run a potentially malicious guest. An IBPB will
65+
* be needed to before running userspace. That IBPB will flush the branch
66+
* predictor content.
67+
*/
68+
DEFINE_PER_CPU(bool, x86_ibpb_exit_to_user);
69+
EXPORT_PER_CPU_SYMBOL_GPL(x86_ibpb_exit_to_user);
70+
6371
u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
6472
EXPORT_SYMBOL_GPL(x86_pred_cmd);
6573

arch/x86/kvm/x86.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11069,6 +11069,15 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
1106911069
if (vcpu->arch.guest_fpu.xfd_err)
1107011070
wrmsrl(MSR_IA32_XFD_ERR, 0);
1107111071

11072+
/*
11073+
* Mark this CPU as needing a branch predictor flush before running
11074+
* userspace. Must be done before enabling preemption to ensure it gets
11075+
* set for the CPU that actually ran the guest, and not the CPU that it
11076+
* may migrate to.
11077+
*/
11078+
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER))
11079+
this_cpu_write(x86_ibpb_exit_to_user, true);
11080+
1107211081
/*
1107311082
* Consume any pending interrupts, including the possible source of
1107411083
* VM-Exit on SVM and any ticks that occur between VM-Exit and now.

0 commit comments

Comments
 (0)