Skip to content

Commit 1500628

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 <dave.hansen@linux.intel.com> Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de> Acked-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 304d1fb commit 1500628

5 files changed

Lines changed: 27 additions & 0 deletions

File tree

arch/x86/include/asm/cpufeatures.h

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

456457
/*
457458
* BUG word(s)

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
8383
* 8 (ia32) bits.
8484
*/
8585
choose_random_kstack_offset(rdtsc());
86+
87+
/* Avoid unnecessary reads of 'x86_ibpb_exit_to_user' */
88+
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
89+
this_cpu_read(x86_ibpb_exit_to_user)) {
90+
indirect_branch_prediction_barrier();
91+
this_cpu_write(x86_ibpb_exit_to_user, false);
92+
}
8693
}
8794
#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare
8895

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

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

395395
extern u64 x86_pred_cmd;
396396

397+
DECLARE_PER_CPU(bool, x86_ibpb_exit_to_user);
398+
397399
static inline void indirect_branch_prediction_barrier(void)
398400
{
399401
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
@@ -59,6 +59,14 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
5959
DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
6060
EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
6161

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

arch/x86/kvm/x86.c

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

10928+
/*
10929+
* Mark this CPU as needing a branch predictor flush before running
10930+
* userspace. Must be done before enabling preemption to ensure it gets
10931+
* set for the CPU that actually ran the guest, and not the CPU that it
10932+
* may migrate to.
10933+
*/
10934+
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER))
10935+
this_cpu_write(x86_ibpb_exit_to_user, true);
10936+
1092810937
/*
1092910938
* Consume any pending interrupts, including the possible source of
1093010939
* VM-Exit on SVM and any ticks that occur between VM-Exit and now.

0 commit comments

Comments
 (0)