@@ -100,9 +100,6 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
{
unsigned cpu = smp_processor_id();
- if (ibpb_inuse && boot_cpu_has(X86_FEATURE_SPEC_CTRL))
- native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB);
-
if (likely(prev != next)) {
this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
this_cpu_write(cpu_tlbstate.active_mm, next);
@@ -140,6 +137,25 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
/* Stop flush ipis for the previous mm */
cpumask_clear_cpu(cpu, mm_cpumask(prev));
+ /*
+ * Avoid user/user BTB poisoning by flushing the branch
+ * predictor when switching between processes. This stops
+ * one process from doing Spectre-v2 attacks on another.
+ *
+ * As an optimization, flush indirect branches only when
+ * switching into processes that disable dumping. This
+ * protects high value processes like gpg, without having
+ * too high performance overhead. IBPB is *expensive*!
+ *
+ * This will not flush branches when switching into kernel
+ * threads. It will flush if we switch to a different
+ * non-dumpable process.
+ */
+ if (tsk && tsk->mm &&
+ get_dumpable(tsk->mm) != SUID_DUMP_USER &&
+ ibpb_inuse && boot_cpu_has(X86_FEATURE_SPEC_CTRL))
+ native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB);
+
/* Load the LDT, if the LDT is different: */
if (unlikely(prev->context.ldt != next->context.ldt))
load_mm_ldt(next);