]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.7/x86speculation_Apply_IBPB_more_strictly_to_avoid_cross-process_data_leak.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.19.7 / x86speculation_Apply_IBPB_more_strictly_to_avoid_cross-process_data_leak.patch
CommitLineData
f440d5c6
GKH
1Subject: x86/speculation: Apply IBPB more strictly to avoid cross-process data leak
2From: Jiri Kosina jkosina@suse.cz
3Date: Tue Sep 25 14:38:18 2018 +0200
4
5From: Jiri Kosina jkosina@suse.cz
6
7commit dbfe2953f63c640463c630746cd5d9de8b2f63ae upstream
8
9Currently, IBPB is only issued in cases when switching into a non-dumpable
10process, the rationale being to protect such 'important and security
11sensitive' processess (such as GPG) from data leaking into a different
12userspace process via spectre v2.
13
14This is however completely insufficient to provide proper userspace-to-userpace
15spectrev2 protection, as any process can poison branch buffers before being
16scheduled out, and the newly scheduled process immediately becomes spectrev2
17victim.
18
19In order to minimize the performance impact (for usecases that do require
20spectrev2 protection), issue the barrier only in cases when switching between
21processess where the victim can't be ptraced by the potential attacker (as in
22such cases, the attacker doesn't have to bother with branch buffers at all).
23
24[ tglx: Split up PTRACE_MODE_NOACCESS_CHK into PTRACE_MODE_SCHED and
25 PTRACE_MODE_IBPB to be able to do ptrace() context tracking reasonably
26 fine-grained ]
27
28Fixes: 18bf3c3ea8 ("x86/speculation: Use Indirect Branch Prediction Barrier in context switch")
29Originally-by: Tim Chen <tim.c.chen@linux.intel.com>
30Signed-off-by: Jiri Kosina <jkosina@suse.cz>
31Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
32Cc: Peter Zijlstra <peterz@infradead.org>
33Cc: Josh Poimboeuf <jpoimboe@redhat.com>
34Cc: Andrea Arcangeli <aarcange@redhat.com>
35Cc: "WoodhouseDavid" <dwmw@amazon.co.uk>
36Cc: Andi Kleen <ak@linux.intel.com>
37Cc: "SchauflerCasey" <casey.schaufler@intel.com>
38Link: https://lkml.kernel.org/r/nycvar.YFH.7.76.1809251437340.15880@cbobk.fhfr.pm
39Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40
41
42---
43 arch/x86/mm/tlb.c | 31 ++++++++++++++++++++-----------
44 include/linux/ptrace.h | 21 +++++++++++++++++++--
45 kernel/ptrace.c | 10 ++++++++++
46 3 files changed, 49 insertions(+), 13 deletions(-)
47
48--- a/arch/x86/mm/tlb.c
49+++ b/arch/x86/mm/tlb.c
50@@ -7,6 +7,7 @@
51 #include <linux/export.h>
52 #include <linux/cpu.h>
53 #include <linux/debugfs.h>
54+#include <linux/ptrace.h>
55
56 #include <asm/tlbflush.h>
57 #include <asm/mmu_context.h>
58@@ -180,6 +181,19 @@ static void sync_current_stack_to_mm(str
59 }
60 }
61
62+static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id)
63+{
64+ /*
65+ * Check if the current (previous) task has access to the memory
66+ * of the @tsk (next) task. If access is denied, make sure to
67+ * issue a IBPB to stop user->user Spectre-v2 attacks.
68+ *
69+ * Note: __ptrace_may_access() returns 0 or -ERRNO.
70+ */
71+ return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id &&
72+ ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB));
73+}
74+
75 void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
76 struct task_struct *tsk)
77 {
78@@ -262,18 +276,13 @@ void switch_mm_irqs_off(struct mm_struct
79 * one process from doing Spectre-v2 attacks on another.
80 *
81 * As an optimization, flush indirect branches only when
82- * switching into processes that disable dumping. This
83- * protects high value processes like gpg, without having
84- * too high performance overhead. IBPB is *expensive*!
85- *
86- * This will not flush branches when switching into kernel
87- * threads. It will also not flush if we switch to idle
88- * thread and back to the same process. It will flush if we
89- * switch to a different non-dumpable process.
90+ * switching into a processes that can't be ptrace by the
91+ * current one (as in such case, attacker has much more
92+ * convenient way how to tamper with the next process than
93+ * branch buffer poisoning).
94 */
95- if (tsk && tsk->mm &&
96- tsk->mm->context.ctx_id != last_ctx_id &&
97- get_dumpable(tsk->mm) != SUID_DUMP_USER)
98+ if (static_cpu_has(X86_FEATURE_USE_IBPB) &&
99+ ibpb_needed(tsk, last_ctx_id))
100 indirect_branch_prediction_barrier();
101
102 if (IS_ENABLED(CONFIG_VMAP_STACK)) {
103--- a/include/linux/ptrace.h
104+++ b/include/linux/ptrace.h
105@@ -62,14 +62,17 @@ extern void exit_ptrace(struct task_stru
106 #define PTRACE_MODE_READ 0x01
107 #define PTRACE_MODE_ATTACH 0x02
108 #define PTRACE_MODE_NOAUDIT 0x04
109-#define PTRACE_MODE_FSCREDS 0x08
110-#define PTRACE_MODE_REALCREDS 0x10
111+#define PTRACE_MODE_FSCREDS 0x08
112+#define PTRACE_MODE_REALCREDS 0x10
113+#define PTRACE_MODE_SCHED 0x20
114+#define PTRACE_MODE_IBPB 0x40
115
116 /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
117 #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
118 #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
119 #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
120 #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
121+#define PTRACE_MODE_SPEC_IBPB (PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_IBPB)
122
123 /**
124 * ptrace_may_access - check whether the caller is permitted to access
125@@ -87,6 +90,20 @@ extern void exit_ptrace(struct task_stru
126 */
127 extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
128
129+/**
130+ * ptrace_may_access - check whether the caller is permitted to access
131+ * a target task.
132+ * @task: target task
133+ * @mode: selects type of access and caller credentials
134+ *
135+ * Returns true on success, false on denial.
136+ *
137+ * Similar to ptrace_may_access(). Only to be called from context switch
138+ * code. Does not call into audit and the regular LSM hooks due to locking
139+ * constraints.
140+ */
141+extern bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode);
142+
143 static inline int ptrace_reparented(struct task_struct *child)
144 {
145 return !same_thread_group(child->real_parent, child->parent);
146--- a/kernel/ptrace.c
147+++ b/kernel/ptrace.c
148@@ -261,6 +261,9 @@ static int ptrace_check_attach(struct ta
149
150 static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
151 {
152+ if (mode & PTRACE_MODE_SCHED)
153+ return false;
154+
155 if (mode & PTRACE_MODE_NOAUDIT)
156 return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
157 else
158@@ -328,9 +331,16 @@ ok:
159 !ptrace_has_cap(mm->user_ns, mode)))
160 return -EPERM;
161
162+ if (mode & PTRACE_MODE_SCHED)
163+ return 0;
164 return security_ptrace_access_check(task, mode);
165 }
166
167+bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode)
168+{
169+ return __ptrace_may_access(task, mode | PTRACE_MODE_SCHED);
170+}
171+
172 bool ptrace_may_access(struct task_struct *task, unsigned int mode)
173 {
174 int err;