]>
Commit | Line | Data |
---|---|---|
e9e21f07 GKH |
1 | From foo@baz Mon Jul 23 10:04:05 CEST 2018 |
2 | From: "Srivatsa S. Bhat" <srivatsa@csail.mit.edu> | |
3 | Date: Sat, 14 Jul 2018 02:36:17 -0700 | |
4 | Subject: nospec: Allow getting/setting on non-current task | |
5 | To: gregkh@linuxfoundation.org, stable@vger.kernel.org | |
6 | Cc: Kees Cook <keescook@chromium.org>, Thomas Gleixner <tglx@linutronix.de>, David Woodhouse <dwmw@amazon.co.uk>, "Matt Helsley \(VMware\)" <matt.helsley@gmail.com>, Alexey Makhalov <amakhalov@vmware.com>, Bo Gan <ganb@vmware.com>, matt.helsley@gmail.com, rostedt@goodmis.org, amakhalov@vmware.com, ganb@vmware.com, srivatsa@csail.mit.edu, srivatsab@vmware.com | |
7 | Message-ID: <153156097734.10043.17651791931697056953.stgit@srivatsa-ubuntu> | |
8 | ||
9 | From: Kees Cook <keescook@chromium.org> | |
10 | ||
11 | commit 7bbf1373e228840bb0295a2ca26d548ef37f448e upstream | |
12 | ||
13 | Adjust arch_prctl_get/set_spec_ctrl() to operate on tasks other than | |
14 | current. | |
15 | ||
16 | This is needed both for /proc/$pid/status queries and for seccomp (since | |
17 | thread-syncing can trigger seccomp in non-current threads). | |
18 | ||
19 | Signed-off-by: Kees Cook <keescook@chromium.org> | |
20 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
21 | Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> | |
22 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
23 | Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu> | |
24 | Reviewed-by: Matt Helsley (VMware) <matt.helsley@gmail.com> | |
25 | Reviewed-by: Alexey Makhalov <amakhalov@vmware.com> | |
26 | Reviewed-by: Bo Gan <ganb@vmware.com> | |
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
28 | --- | |
29 | ||
30 | arch/x86/kernel/cpu/bugs.c | 27 ++++++++++++++++----------- | |
31 | include/linux/nospec.h | 7 +++++-- | |
32 | kernel/sys.c | 9 +++++---- | |
33 | 3 files changed, 26 insertions(+), 17 deletions(-) | |
34 | ||
35 | --- a/arch/x86/kernel/cpu/bugs.c | |
36 | +++ b/arch/x86/kernel/cpu/bugs.c | |
37 | @@ -529,31 +529,35 @@ static void ssb_select_mitigation() | |
38 | ||
39 | #undef pr_fmt | |
40 | ||
41 | -static int ssb_prctl_set(unsigned long ctrl) | |
42 | +static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) | |
43 | { | |
44 | - bool rds = !!test_tsk_thread_flag(current, TIF_RDS); | |
45 | + bool rds = !!test_tsk_thread_flag(task, TIF_RDS); | |
46 | ||
47 | if (ssb_mode != SPEC_STORE_BYPASS_PRCTL) | |
48 | return -ENXIO; | |
49 | ||
50 | if (ctrl == PR_SPEC_ENABLE) | |
51 | - clear_tsk_thread_flag(current, TIF_RDS); | |
52 | + clear_tsk_thread_flag(task, TIF_RDS); | |
53 | else | |
54 | - set_tsk_thread_flag(current, TIF_RDS); | |
55 | + set_tsk_thread_flag(task, TIF_RDS); | |
56 | ||
57 | - if (rds != !!test_tsk_thread_flag(current, TIF_RDS)) | |
58 | + /* | |
59 | + * If being set on non-current task, delay setting the CPU | |
60 | + * mitigation until it is next scheduled. | |
61 | + */ | |
62 | + if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS)) | |
63 | speculative_store_bypass_update(); | |
64 | ||
65 | return 0; | |
66 | } | |
67 | ||
68 | -static int ssb_prctl_get(void) | |
69 | +static int ssb_prctl_get(struct task_struct *task) | |
70 | { | |
71 | switch (ssb_mode) { | |
72 | case SPEC_STORE_BYPASS_DISABLE: | |
73 | return PR_SPEC_DISABLE; | |
74 | case SPEC_STORE_BYPASS_PRCTL: | |
75 | - if (test_tsk_thread_flag(current, TIF_RDS)) | |
76 | + if (test_tsk_thread_flag(task, TIF_RDS)) | |
77 | return PR_SPEC_PRCTL | PR_SPEC_DISABLE; | |
78 | return PR_SPEC_PRCTL | PR_SPEC_ENABLE; | |
79 | default: | |
80 | @@ -563,24 +567,25 @@ static int ssb_prctl_get(void) | |
81 | } | |
82 | } | |
83 | ||
84 | -int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl) | |
85 | +int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, | |
86 | + unsigned long ctrl) | |
87 | { | |
88 | if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE) | |
89 | return -ERANGE; | |
90 | ||
91 | switch (which) { | |
92 | case PR_SPEC_STORE_BYPASS: | |
93 | - return ssb_prctl_set(ctrl); | |
94 | + return ssb_prctl_set(task, ctrl); | |
95 | default: | |
96 | return -ENODEV; | |
97 | } | |
98 | } | |
99 | ||
100 | -int arch_prctl_spec_ctrl_get(unsigned long which) | |
101 | +int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) | |
102 | { | |
103 | switch (which) { | |
104 | case PR_SPEC_STORE_BYPASS: | |
105 | - return ssb_prctl_get(); | |
106 | + return ssb_prctl_get(task); | |
107 | default: | |
108 | return -ENODEV; | |
109 | } | |
110 | --- a/include/linux/nospec.h | |
111 | +++ b/include/linux/nospec.h | |
112 | @@ -7,6 +7,8 @@ | |
113 | #define _LINUX_NOSPEC_H | |
114 | #include <asm/barrier.h> | |
115 | ||
116 | +struct task_struct; | |
117 | + | |
118 | /** | |
119 | * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise | |
120 | * @index: array element index | |
121 | @@ -57,7 +59,8 @@ static inline unsigned long array_index_ | |
122 | }) | |
123 | ||
124 | /* Speculation control prctl */ | |
125 | -int arch_prctl_spec_ctrl_get(unsigned long which); | |
126 | -int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl); | |
127 | +int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which); | |
128 | +int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, | |
129 | + unsigned long ctrl); | |
130 | ||
131 | #endif /* _LINUX_NOSPEC_H */ | |
132 | --- a/kernel/sys.c | |
133 | +++ b/kernel/sys.c | |
134 | @@ -2075,12 +2075,13 @@ static int prctl_get_tid_address(struct | |
135 | } | |
136 | #endif | |
137 | ||
138 | -int __weak arch_prctl_spec_ctrl_get(unsigned long which) | |
139 | +int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which) | |
140 | { | |
141 | return -EINVAL; | |
142 | } | |
143 | ||
144 | -int __weak arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl) | |
145 | +int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which, | |
146 | + unsigned long ctrl) | |
147 | { | |
148 | return -EINVAL; | |
149 | } | |
150 | @@ -2282,12 +2283,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi | |
151 | case PR_GET_SPECULATION_CTRL: | |
152 | if (arg3 || arg4 || arg5) | |
153 | return -EINVAL; | |
154 | - error = arch_prctl_spec_ctrl_get(arg2); | |
155 | + error = arch_prctl_spec_ctrl_get(me, arg2); | |
156 | break; | |
157 | case PR_SET_SPECULATION_CTRL: | |
158 | if (arg4 || arg5) | |
159 | return -EINVAL; | |
160 | - error = arch_prctl_spec_ctrl_set(arg2, arg3); | |
161 | + error = arch_prctl_spec_ctrl_set(me, arg2, arg3); | |
162 | break; | |
163 | default: | |
164 | error = -EINVAL; |