]>
Commit | Line | Data |
---|---|---|
035dbe67 FG |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Tim Chen <tim.c.chen@linux.intel.com> | |
3 | Date: Tue, 7 Nov 2017 13:52:42 -0800 | |
4 | Subject: [PATCH] x86/mm: Only set IBPB when the new thread cannot ptrace | |
5 | current thread | |
6 | MIME-Version: 1.0 | |
7 | Content-Type: text/plain; charset=UTF-8 | |
8 | Content-Transfer-Encoding: 8bit | |
9 | ||
10 | CVE-2017-5753 | |
11 | CVE-2017-5715 | |
12 | ||
13 | To reduce overhead of setting IBPB, we only do that when | |
14 | the new thread cannot ptrace the current one. If the new | |
15 | thread has ptrace capability on current thread, it is safe. | |
16 | ||
17 | Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com> | |
18 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
19 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
20 | (cherry picked from commit 65941af723059ffeeca269b99ab51b3c9e320751) | |
21 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
22 | --- | |
23 | include/linux/ptrace.h | 6 ++++++ | |
24 | arch/x86/mm/tlb.c | 5 ++++- | |
25 | kernel/ptrace.c | 18 ++++++++++++++---- | |
26 | 3 files changed, 24 insertions(+), 5 deletions(-) | |
27 | ||
28 | diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h | |
29 | index 0e5fcc11b1b8..d6afefd5465b 100644 | |
30 | --- a/include/linux/ptrace.h | |
31 | +++ b/include/linux/ptrace.h | |
32 | @@ -63,12 +63,15 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead); | |
33 | #define PTRACE_MODE_NOAUDIT 0x04 | |
34 | #define PTRACE_MODE_FSCREDS 0x08 | |
35 | #define PTRACE_MODE_REALCREDS 0x10 | |
36 | +#define PTRACE_MODE_NOACCESS_CHK 0x20 | |
37 | ||
38 | /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */ | |
39 | #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS) | |
40 | #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS) | |
41 | #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS) | |
42 | #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS) | |
43 | +#define PTRACE_MODE_IBPB (PTRACE_MODE_ATTACH | PTRACE_MODE_NOAUDIT \ | |
44 | + | PTRACE_MODE_NOACCESS_CHK | PTRACE_MODE_REALCREDS) | |
45 | ||
46 | /** | |
47 | * ptrace_may_access - check whether the caller is permitted to access | |
48 | @@ -86,6 +89,9 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead); | |
49 | */ | |
50 | extern bool ptrace_may_access(struct task_struct *task, unsigned int mode); | |
51 | ||
52 | +extern int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task, | |
53 | + unsigned int mode); | |
54 | + | |
55 | static inline int ptrace_reparented(struct task_struct *child) | |
56 | { | |
57 | return !same_thread_group(child->real_parent, child->parent); | |
58 | diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c | |
59 | index bb3ded3a4e5f..301e6efbc514 100644 | |
60 | --- a/arch/x86/mm/tlb.c | |
61 | +++ b/arch/x86/mm/tlb.c | |
62 | @@ -6,6 +6,7 @@ | |
63 | #include <linux/interrupt.h> | |
64 | #include <linux/export.h> | |
65 | #include <linux/cpu.h> | |
66 | +#include <linux/ptrace.h> | |
67 | ||
68 | #include <asm/tlbflush.h> | |
69 | #include <asm/mmu_context.h> | |
70 | @@ -219,7 +220,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | |
71 | u16 new_asid; | |
72 | bool need_flush; | |
73 | ||
74 | - if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) | |
75 | + /* Null tsk means switching to kernel, so that's safe */ | |
76 | + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && tsk && | |
77 | + ___ptrace_may_access(tsk, current, PTRACE_MODE_IBPB)) | |
78 | native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB); | |
79 | ||
80 | if (IS_ENABLED(CONFIG_VMAP_STACK)) { | |
81 | diff --git a/kernel/ptrace.c b/kernel/ptrace.c | |
82 | index 60f356d91060..f2f0f1aeabaf 100644 | |
83 | --- a/kernel/ptrace.c | |
84 | +++ b/kernel/ptrace.c | |
85 | @@ -268,9 +268,10 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) | |
86 | } | |
87 | ||
88 | /* Returns 0 on success, -errno on denial. */ | |
89 | -static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |
90 | +int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task, | |
91 | + unsigned int mode) | |
92 | { | |
93 | - const struct cred *cred = current_cred(), *tcred; | |
94 | + const struct cred *cred = __task_cred(cur), *tcred; | |
95 | struct mm_struct *mm; | |
96 | kuid_t caller_uid; | |
97 | kgid_t caller_gid; | |
98 | @@ -290,7 +291,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |
99 | */ | |
100 | ||
101 | /* Don't let security modules deny introspection */ | |
102 | - if (same_thread_group(task, current)) | |
103 | + if (same_thread_group(task, cur)) | |
104 | return 0; | |
105 | rcu_read_lock(); | |
106 | if (mode & PTRACE_MODE_FSCREDS) { | |
107 | @@ -328,7 +329,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |
108 | !ptrace_has_cap(mm->user_ns, mode))) | |
109 | return -EPERM; | |
110 | ||
111 | - return security_ptrace_access_check(task, mode); | |
112 | + if (!(mode & PTRACE_MODE_NOACCESS_CHK)) | |
113 | + return security_ptrace_access_check(task, mode); | |
114 | + | |
115 | + return 0; | |
116 | +} | |
117 | +EXPORT_SYMBOL_GPL(___ptrace_may_access); | |
118 | + | |
119 | +static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |
120 | +{ | |
121 | + return ___ptrace_may_access(current, task, mode); | |
122 | } | |
123 | ||
124 | bool ptrace_may_access(struct task_struct *task, unsigned int mode) | |
125 | -- | |
126 | 2.14.2 | |
127 |