[PATCH] x86/speculation, KVM: respect user IBPB configuration

From: Jon Kohler
Date: Mon Apr 11 2022 - 12:48:21 EST


On vmx_vcpu_load_vmcs and svm_vcpu_load, respect user IBPB config and only
attempt IBPB MSR if either always_ibpb or cond_ibpb and the vcpu thread
has TIF_SPEC_IB.

A vcpu thread will have TIF_SPEC_IB on qemu-kvm using -sandbox on if
kernel cmdline spectre_v2_user=seccomp, which would indicate that the user
is looking for a higher security environment and has workloads that need
to be secured from each other.

Note: The behavior of spectre_v2_user recently changed in 5.16 on
commit 2f46993d83ff ("x86: change default to
spec_store_bypass_disable=prctl spectre_v2_user=prctl")

Prior to that, qemu-kvm with -sandbox on would also have TIF_SPEC_IB
if spectre_v2_user=auto.

Signed-off-by: Jon Kohler <jon@xxxxxxxxxxx>
Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx>
Cc: Kees Cook <keescook@xxxxxxxxxxxx>
Cc: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
Cc: Waiman Long <longman@xxxxxxxxxx>
---
arch/x86/include/asm/spec-ctrl.h | 12 ++++++++++++
arch/x86/kernel/cpu/bugs.c | 6 ++++--
arch/x86/kvm/svm/svm.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 2 +-
4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
index 5393babc0598..552757847d5b 100644
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -85,4 +85,16 @@ static inline void speculative_store_bypass_ht_init(void) { }
extern void speculation_ctrl_update(unsigned long tif);
extern void speculation_ctrl_update_current(void);

+/*
+ * Always issue IBPB if switch_mm_always_ibpb and respect conditional
+ * IBPB if this thread does not have !TIF_SPEC_IB.
+ */
+static inline void maybe_indirect_branch_prediction_barrier(void)
+{
+ if (static_key_enabled(&switch_mm_always_ibpb) ||
+ (static_key_enabled(&switch_mm_cond_ibpb) &&
+ test_thread_flag(TIF_SPEC_IB)))
+ indirect_branch_prediction_barrier();
+}
+
#endif
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6296e1ebed1d..737826bf974c 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -66,10 +66,12 @@ u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;

/* Control conditional STIBP in switch_to() */
DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
-/* Control conditional IBPB in switch_mm() */
+/* Control conditional IBPB in switch_mm() and vmcs/vmcb load */
DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
-/* Control unconditional IBPB in switch_mm() */
+EXPORT_SYMBOL_GPL(switch_mm_cond_ibpb);
+/* Control unconditional IBPB in switch_mm() and vmcs/vmcb load */
DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+EXPORT_SYMBOL_GPL(switch_mm_always_ibpb);

/* Control MDS CPU buffer clear before returning to user space */
DEFINE_STATIC_KEY_FALSE(mds_user_clear);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index bd4c64b362d2..7762ca1197b5 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1302,7 +1302,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)

if (sd->current_vmcb != svm->vmcb) {
sd->current_vmcb = svm->vmcb;
- indirect_branch_prediction_barrier();
+ maybe_indirect_branch_prediction_barrier();
}
if (kvm_vcpu_apicv_active(vcpu))
__avic_vcpu_load(vcpu, cpu);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 04d170c4b61e..baaf658263b5 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1270,7 +1270,7 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
* The L1 VMM can protect itself with retpolines, IBPB or IBRS.
*/
if (!buddy || WARN_ON_ONCE(buddy->vmcs != prev))
- indirect_branch_prediction_barrier();
+ maybe_indirect_branch_prediction_barrier();
}

if (!already_loaded) {
--
2.30.1 (Apple Git-130)