All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Peter Zijlstra <peterz@infradead.org>,
	Andy Lutomirski <luto@kernel.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Jiri Kosina <jkosina@suse.cz>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	David Woodhouse <dwmw@amazon.co.uk>,
	Andi Kleen <ak@linux.intel.com>,
	Dave Hansen <dave.hansen@intel.com>,
	Casey Schaufler <casey.schaufler@intel.com>,
	Asit Mallick <asit.k.mallick@intel.com>,
	Arjan van de Ven <arjan@linux.intel.com>,
	Jon Masters <jcm@redhat.com>, Waiman Long <longman9394@gmail.com>,
	Greg KH <gregkh@linuxfoundation.org>,
	Dave Stewart <david.c.stewart@intel.com>,
	Kees Cook <keescook@chromium.org>
Subject: [patch 17/24] x86/speculation: Move IBPB control out of switch_mm()
Date: Wed, 21 Nov 2018 21:14:47 +0100	[thread overview]
Message-ID: <20181121201723.948990148@linutronix.de> (raw)
In-Reply-To: 20181121201430.559770965@linutronix.de

[-- Attachment #1: x86-speculation--Move-IBPB-control-out-of-switch_mm--.patch --]
[-- Type: text/plain, Size: 10219 bytes --]

IBPB control is currently in switch_mm() to avoid issuing IBPB when
switching between tasks of the same process.

But that's not covering the case of sandboxed tasks which get the
TIF_SPEC_IB flag set via seccomp. There the barrier is required when the
potentially malicious task is switched out because the task which is
switched in might have it not set and would still be attackable.

For tasks which mark themself with TIF_SPEC_IB via the prctl, the barrier
needs to be when the tasks switches in because the previous one might be an
attacker.

Move the code out of switch_mm() and evaluate the TIF bit in
switch_to(). Make it an inline function so it can be used both in 32bit and
64bit code.

This loses the optimization of switching back to the same process, but
that's wrong in the context of seccomp anyway as it does not protect tasks
of the same process against each other.

This could be optimized by keeping track of the last user task per cpu and
avoiding the barrier when the task is immediately scheduled back and the
thread inbetween was a kernel thread. It's dubious whether that'd be worth
the extra load/store and conditional operations. Keep it optimized for the
common case where the TIF bit is not set.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/nospec-branch.h |    2 +
 arch/x86/include/asm/spec-ctrl.h     |   46 +++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/tlbflush.h      |    2 -
 arch/x86/kernel/cpu/bugs.c           |   16 +++++++++++-
 arch/x86/kernel/process_32.c         |   11 ++++++--
 arch/x86/kernel/process_64.c         |   11 ++++++--
 arch/x86/mm/tlb.c                    |   39 -----------------------------
 7 files changed, 81 insertions(+), 46 deletions(-)

--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -312,6 +312,8 @@ do {									\
 } while (0)
 
 DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+DECLARE_STATIC_KEY_FALSE(switch_to_cond_ibpb);
+DECLARE_STATIC_KEY_FALSE(switch_to_always_ibpb);
 
 #endif /* __ASSEMBLY__ */
 
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -76,6 +76,52 @@ static inline u64 ssbd_tif_to_amd_ls_cfg
 	return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
 }
 
+/**
+ * switch_to_ibpb - Issue IBPB on task switch
+ * @next:	Pointer to the next task
+ * @prev_tif:	Threadinfo flags of the previous task
+ * @next_tif:	Threadinfo flags of the next task
+ *
+ * IBPB flushes the branch predictor, which stops Spectre-v2 attacks
+ * between user space tasks. Depending on the mode the flush is made
+ * conditional.
+ */
+static inline void switch_to_ibpb(struct task_struct *next,
+				  unsigned long prev_tif,
+				  unsigned long next_tif)
+{
+	if (static_branch_unlikely(&switch_to_always_ibpb)) {
+		/* Only flush when switching to a user task. */
+		if (next->mm)
+			indirect_branch_prediction_barrier();
+	}
+
+	if (static_branch_unlikely(&switch_to_cond_ibpb)) {
+		/*
+		 * Both tasks' threadinfo flags are checked for TIF_SPEC_IB.
+		 *
+		 * For an outgoing sandboxed task which has TIF_SPEC_IB set
+		 * via seccomp this is needed because it might be malicious
+		 * and the next user task switching in might not have it
+		 * set.
+		 *
+		 * For an incoming task which has set TIF_SPEC_IB itself
+		 * via prctl() this is needed because the previous user
+		 * task might be malicious and have the flag unset.
+		 *
+		 * This could be optimized by keeping track of the last
+		 * user task per cpu and avoiding the barrier when the task
+		 * is immediately scheduled back and the thread inbetween
+		 * was a kernel thread. It's dubious whether that'd be
+		 * worth the extra load/store and conditional operations.
+		 * Keep it optimized for the common case where the TIF bit
+		 * is not set.
+		 */
+		if ((prev_tif | next_tif) & _TIF_SPEC_IB)
+			indirect_branch_prediction_barrier();
+	}
+}
+
 #ifdef CONFIG_SMP
 extern void speculative_store_bypass_ht_init(void);
 #else
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -171,8 +171,6 @@ struct tlb_state {
 
 	u16 loaded_mm_asid;
 	u16 next_asid;
-	/* last user mm's ctx id */
-	u64 last_ctx_id;
 
 	/*
 	 * We can be in one of several states:
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -56,6 +56,10 @@ u64 __ro_after_init x86_amd_ls_cfg_ssbd_
 
 /* Control conditional STIPB in switch_to() */
 DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+/* Control conditional IBPB in switch_to() */
+DEFINE_STATIC_KEY_FALSE(switch_to_cond_ibpb);
+/* Control unconditional IBPB in switch_to() */
+DEFINE_STATIC_KEY_FALSE(switch_to_always_ibpb);
 
 void __init check_bugs(void)
 {
@@ -331,7 +335,17 @@ spectre_v2_app2app_select_mitigation(enu
 	/* Initialize Indirect Branch Prediction Barrier */
 	if (boot_cpu_has(X86_FEATURE_IBPB)) {
 		setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
-		pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
+
+		switch (mode) {
+		case SPECTRE_V2_APP2APP_STRICT:
+			static_branch_enable(&switch_to_always_ibpb);
+			break;
+		default:
+			break;
+		}
+
+		pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
+			mode == SPECTRE_V2_APP2APP_STRICT ? "forced" : "conditional");
 	}
 
 	/* If enhanced IBRS is enabled no STIPB required */
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -58,6 +58,7 @@
 #include <asm/vm86.h>
 #include <asm/intel_rdt_sched.h>
 #include <asm/proto.h>
+#include <asm/spec-ctrl.h>
 
 void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
 {
@@ -231,6 +232,7 @@ EXPORT_SYMBOL_GPL(start_thread);
 			     *next = &next_p->thread;
 	struct fpu *prev_fpu = &prev->fpu;
 	struct fpu *next_fpu = &next->fpu;
+	unsigned long prev_tif, next_tif;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
@@ -264,11 +266,16 @@ EXPORT_SYMBOL_GPL(start_thread);
 	if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
 		set_iopl_mask(next->iopl);
 
+	prev_tif = task_thread_info(prev_p)->flags;
+	next_tif = task_thread_info(next_p)->flags;
+	/* Indirect branch prediction barrier control */
+	switch_to_ibpb(next_p, prev_tif, next_tif);
+
 	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
 	 */
-	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
-		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
+	if (unlikely(next_tif & _TIF_WORK_CTXSW_NEXT ||
+		     prev_tif & _TIF_WORK_CTXSW_PREV))
 		__switch_to_xtra(prev_p, next_p, tss);
 
 	/*
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -55,6 +55,7 @@
 #include <asm/intel_rdt_sched.h>
 #include <asm/unistd.h>
 #include <asm/fsgsbase.h>
+#include <asm/spec-ctrl.h>
 #ifdef CONFIG_IA32_EMULATION
 /* Not included via unistd.h */
 #include <asm/unistd_32_ia32.h>
@@ -552,6 +553,7 @@ void compat_start_thread(struct pt_regs
 	struct thread_struct *next = &next_p->thread;
 	struct fpu *prev_fpu = &prev->fpu;
 	struct fpu *next_fpu = &next->fpu;
+	unsigned long prev_tif, next_tif;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
@@ -617,11 +619,16 @@ void compat_start_thread(struct pt_regs
 	/* Reload sp0. */
 	update_task_stack(next_p);
 
+	prev_tif = task_thread_info(prev_p)->flags;
+	next_tif = task_thread_info(next_p)->flags;
+	/* Indirect branch prediction barrier control */
+	switch_to_ibpb(next_p, prev_tif, next_tif);
+
 	/*
 	 * Now maybe reload the debug registers and handle I/O bitmaps
 	 */
-	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
-		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
+	if (unlikely(next_tif & _TIF_WORK_CTXSW_NEXT ||
+		     prev_tif & _TIF_WORK_CTXSW_PREV))
 		__switch_to_xtra(prev_p, next_p, tss);
 
 #ifdef CONFIG_XEN_PV
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -181,19 +181,6 @@ static void sync_current_stack_to_mm(str
 	}
 }
 
-static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id)
-{
-	/*
-	 * Check if the current (previous) task has access to the memory
-	 * of the @tsk (next) task. If access is denied, make sure to
-	 * issue a IBPB to stop user->user Spectre-v2 attacks.
-	 *
-	 * Note: __ptrace_may_access() returns 0 or -ERRNO.
-	 */
-	return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id &&
-		ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB));
-}
-
 void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
 			struct task_struct *tsk)
 {
@@ -292,23 +279,6 @@ void switch_mm_irqs_off(struct mm_struct
 		new_asid = prev_asid;
 		need_flush = true;
 	} else {
-		u64 last_ctx_id = this_cpu_read(cpu_tlbstate.last_ctx_id);
-
-		/*
-		 * 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 a processes that can't be ptrace by the
-		 * current one (as in such case, attacker has much more
-		 * convenient way how to tamper with the next process than
-		 * branch buffer poisoning).
-		 */
-		if (static_cpu_has(X86_FEATURE_USE_IBPB) &&
-				ibpb_needed(tsk, last_ctx_id))
-			indirect_branch_prediction_barrier();
-
 		if (IS_ENABLED(CONFIG_VMAP_STACK)) {
 			/*
 			 * If our current stack is in vmalloc space and isn't
@@ -365,14 +335,6 @@ void switch_mm_irqs_off(struct mm_struct
 		trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
 	}
 
-	/*
-	 * Record last user mm's context id, so we can avoid
-	 * flushing branch buffer with IBPB if we switch back
-	 * to the same user.
-	 */
-	if (next != &init_mm)
-		this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id);
-
 	/* Make sure we write CR3 before loaded_mm. */
 	barrier();
 
@@ -441,7 +403,6 @@ void initialize_tlbstate_and_flush(void)
 	write_cr3(build_cr3(mm->pgd, 0));
 
 	/* Reinitialize tlbstate. */
-	this_cpu_write(cpu_tlbstate.last_ctx_id, mm->context.ctx_id);
 	this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0);
 	this_cpu_write(cpu_tlbstate.next_asid, 1);
 	this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id);



  parent reply	other threads:[~2018-11-21 20:18 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-21 20:14 [patch 00/24] x86/speculation: Remedy the STIBP/IBPB overhead Thomas Gleixner
2018-11-21 20:14 ` [patch 01/24] x86/speculation: Update the TIF_SSBD comment Thomas Gleixner
2018-11-21 20:28   ` Linus Torvalds
2018-11-21 20:30     ` Thomas Gleixner
2018-11-21 20:33     ` Linus Torvalds
2018-11-21 22:48       ` Thomas Gleixner
2018-11-21 22:53         ` Borislav Petkov
2018-11-21 22:55           ` Thomas Gleixner
2018-11-21 22:55           ` Arjan van de Ven
2018-11-21 22:56             ` Borislav Petkov
2018-11-21 23:07               ` Borislav Petkov
2018-11-21 23:04         ` Josh Poimboeuf
2018-11-21 23:08           ` Borislav Petkov
2018-11-22 17:30             ` Josh Poimboeuf
2018-11-22 17:52               ` Borislav Petkov
2018-11-22 21:17                 ` Thomas Gleixner
2018-11-21 20:14 ` [patch 02/24] x86/speculation: Clean up spectre_v2_parse_cmdline() Thomas Gleixner
2018-11-21 20:14 ` [patch 03/24] x86/speculation: Remove unnecessary ret variable in cpu_show_common() Thomas Gleixner
2018-11-21 20:14 ` [patch 04/24] x86/speculation: Reorganize cpu_show_common() Thomas Gleixner
2018-11-21 20:14 ` [patch 05/24] x86/speculation: Disable STIBP when enhanced IBRS is in use Thomas Gleixner
2018-11-21 20:33   ` Borislav Petkov
2018-11-21 20:36     ` Thomas Gleixner
2018-11-21 22:01       ` Thomas Gleixner
2018-11-21 20:14 ` [patch 06/24] x86/speculation: Rename SSBD update functions Thomas Gleixner
2018-11-21 20:14 ` [patch 07/24] x86/speculation: Reorganize speculation control MSRs update Thomas Gleixner
2018-11-21 20:14 ` [patch 08/24] sched/smt: Make sched_smt_present track topology Thomas Gleixner
2018-11-21 20:14 ` [patch 09/24] x86/Kconfig: Select SCHED_SMT if SMP enabled Thomas Gleixner
2018-11-21 20:14 ` [patch 10/24] sched/smt: Expose sched_smt_present static key Thomas Gleixner
2018-11-21 20:41   ` Thomas Gleixner
2018-11-21 20:14 ` [patch 11/24] x86/speculation: Rework SMT state change Thomas Gleixner
2018-11-21 20:14 ` [patch 12/24] x86/l1tf: Show actual SMT state Thomas Gleixner
2018-11-21 20:14 ` [patch 13/24] x86/speculation: Reorder the spec_v2 code Thomas Gleixner
2018-11-21 20:14 ` [patch 14/24] x86/speculation: Unify conditional spectre v2 print functions Thomas Gleixner
2018-11-22  7:59   ` Ingo Molnar
2018-11-21 20:14 ` [patch 15/24] x86/speculation: Add command line control for indirect branch speculation Thomas Gleixner
2018-11-21 23:43   ` Borislav Petkov
2018-11-22  8:14     ` Thomas Gleixner
2018-11-22  9:07       ` Thomas Gleixner
2018-11-22  9:18       ` Peter Zijlstra
2018-11-22 10:10         ` Borislav Petkov
2018-11-22 10:48           ` Thomas Gleixner
2018-11-21 20:14 ` [patch 16/24] x86/speculation: Prepare for per task indirect branch speculation control Thomas Gleixner
2018-11-22  7:57   ` Ingo Molnar
2018-11-21 20:14 ` Thomas Gleixner [this message]
2018-11-22  0:01   ` [patch 17/24] x86/speculation: Move IBPB control out of switch_mm() Andi Kleen
2018-11-22  7:42     ` Jiri Kosina
2018-11-22  9:18       ` Thomas Gleixner
2018-11-22  1:40   ` Tim Chen
2018-11-22  7:52   ` Ingo Molnar
2018-11-22 22:29     ` Thomas Gleixner
2018-11-21 20:14 ` [patch 18/24] x86/speculation: Avoid __switch_to_xtra() calls Thomas Gleixner
2018-11-22  1:23   ` Tim Chen
2018-11-22  7:44     ` Ingo Molnar
2018-11-21 20:14 ` [patch 19/24] ptrace: Remove unused ptrace_may_access_sched() and MODE_IBRS Thomas Gleixner
2018-11-21 20:14 ` [patch 20/24] x86/speculation: Split out TIF update Thomas Gleixner
2018-11-22  2:13   ` Tim Chen
2018-11-22 23:00     ` Thomas Gleixner
2018-11-23  7:37       ` Ingo Molnar
2018-11-26 18:35         ` Tim Chen
2018-11-26 21:55           ` Thomas Gleixner
2018-11-27  7:05             ` Jiri Kosina
2018-11-27  7:13               ` Thomas Gleixner
2018-11-27  7:30                 ` Jiri Kosina
2018-11-27 12:52                   ` Jiri Kosina
2018-11-27 13:18                     ` Jiri Kosina
2018-11-27 21:57                     ` Thomas Gleixner
2018-11-27 22:07                       ` Jiri Kosina
2018-11-27 22:20                         ` Jiri Kosina
2018-11-27 22:36                         ` Thomas Gleixner
2018-11-28  1:50                           ` Tim Chen
2018-11-28 10:43                             ` Thomas Gleixner
2018-11-28  6:05                           ` Jiri Kosina
2018-11-28 14:33                       ` [tip:x86/pti] x86/speculation: Prevent stale SPEC_CTRL msr content tip-bot for Thomas Gleixner
2018-11-22  7:43   ` [patch 20/24] x86/speculation: Split out TIF update Ingo Molnar
2018-11-22 23:04     ` Thomas Gleixner
2018-11-23  7:37       ` Ingo Molnar
2018-11-21 20:14 ` [patch 21/24] x86/speculation: Prepare arch_smt_update() for PRCTL mode Thomas Gleixner
2018-11-22  7:34   ` Ingo Molnar
2018-11-22 23:17     ` Thomas Gleixner
2018-11-22 23:28       ` Jiri Kosina
2018-11-21 20:14 ` [patch 22/24] x86/speculation: Create PRCTL interface to restrict indirect branch speculation Thomas Gleixner
2018-11-22  7:10   ` Ingo Molnar
2018-11-22  9:03   ` Peter Zijlstra
2018-11-22  9:08     ` Thomas Gleixner
2018-11-22 12:26   ` Borislav Petkov
2018-11-22 12:33     ` Peter Zijlstra
2018-11-21 20:14 ` [patch 23/24] x86/speculation: Enable PRCTL mode for spectre_v2_app2app Thomas Gleixner
2018-11-22  7:17   ` Ingo Molnar
2018-11-21 20:14 ` [patch 24/24] x86/speculation: Add seccomp Spectre v2 app to app protection mode Thomas Gleixner
2018-11-22  2:24   ` Tim Chen
2018-11-22  7:26   ` Ingo Molnar
2018-11-22 23:45     ` Thomas Gleixner
2018-11-21 23:48 ` [patch 00/24] x86/speculation: Remedy the STIBP/IBPB overhead Tim Chen
2018-11-22  9:55   ` Thomas Gleixner
2018-11-22  9:45 ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181121201723.948990148@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=aarcange@redhat.com \
    --cc=ak@linux.intel.com \
    --cc=arjan@linux.intel.com \
    --cc=asit.k.mallick@intel.com \
    --cc=casey.schaufler@intel.com \
    --cc=dave.hansen@intel.com \
    --cc=david.c.stewart@intel.com \
    --cc=dwmw@amazon.co.uk \
    --cc=gregkh@linuxfoundation.org \
    --cc=jcm@redhat.com \
    --cc=jkosina@suse.cz \
    --cc=jpoimboe@redhat.com \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman9394@gmail.com \
    --cc=luto@kernel.org \
    --cc=peterz@infradead.org \
    --cc=thomas.lendacky@amd.com \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.