blob: 79f9397998ed4b7458d5b4cc227fc83bf703520f [file] [log] [blame]
Michael Ellerman9a868f62018-03-27 23:01:44 +11001// SPDX-License-Identifier: GPL-2.0+
2//
3// Security related flags and so on.
4//
5// Copyright 2018, Michael Ellerman, IBM Corporation.
6
7#include <linux/kernel.h>
Michael Ellerman8ad33042018-03-27 23:01:48 +11008#include <linux/device.h>
Michael Ellermanff348352018-03-27 23:01:49 +11009#include <linux/seq_buf.h>
Michael Ellerman8ad33042018-03-27 23:01:48 +110010
Nicholas Piggina048a072018-05-22 09:00:00 +100011#include <asm/debugfs.h>
Michael Ellerman9a868f62018-03-27 23:01:44 +110012#include <asm/security_features.h>
Michal Suchanek2eea7f02018-04-24 14:15:55 +100013#include <asm/setup.h>
Michael Ellerman9a868f62018-03-27 23:01:44 +110014
15
Mauricio Faria de Oliveirae7347a82018-03-30 14:28:24 -030016unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
Michael Ellerman8ad33042018-03-27 23:01:48 +110017
Michal Suchanek815069c2018-04-24 14:15:56 +100018bool barrier_nospec_enabled;
Diana Craciuncf175dc2018-07-28 09:06:32 +100019static bool no_nospec;
Michal Suchanek2eea7f02018-04-24 14:15:55 +100020
21static void enable_barrier_nospec(bool enable)
22{
23 barrier_nospec_enabled = enable;
24 do_barrier_nospec_fixups(enable);
25}
26
Michal Suchanekcb3d6752018-04-24 14:15:57 +100027void setup_barrier_nospec(void)
28{
29 bool enable;
30
31 /*
32 * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well.
33 * But there's a good reason not to. The two flags we check below are
34 * both are enabled by default in the kernel, so if the hcall is not
35 * functional they will be enabled.
36 * On a system where the host firmware has been updated (so the ori
37 * functions as a barrier), but on which the hypervisor (KVM/Qemu) has
38 * not been updated, we would like to enable the barrier. Dropping the
39 * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is
40 * we potentially enable the barrier on systems where the host firmware
41 * is not updated, but that's harmless as it's a no-op.
42 */
43 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
44 security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
45
Diana Craciuncf175dc2018-07-28 09:06:32 +100046 if (!no_nospec)
47 enable_barrier_nospec(enable);
Michal Suchanekcb3d6752018-04-24 14:15:57 +100048}
49
Diana Craciuncf175dc2018-07-28 09:06:32 +100050static int __init handle_nospectre_v1(char *p)
51{
52 no_nospec = true;
53
54 return 0;
55}
56early_param("nospectre_v1", handle_nospectre_v1);
57
Michal Suchanekcb3d6752018-04-24 14:15:57 +100058#ifdef CONFIG_DEBUG_FS
59static int barrier_nospec_set(void *data, u64 val)
60{
61 switch (val) {
62 case 0:
63 case 1:
64 break;
65 default:
66 return -EINVAL;
67 }
68
69 if (!!val == !!barrier_nospec_enabled)
70 return 0;
71
72 enable_barrier_nospec(!!val);
73
74 return 0;
75}
76
77static int barrier_nospec_get(void *data, u64 *val)
78{
79 *val = barrier_nospec_enabled ? 1 : 0;
80 return 0;
81}
82
83DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec,
84 barrier_nospec_get, barrier_nospec_set, "%llu\n");
85
86static __init int barrier_nospec_debugfs_init(void)
87{
88 debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL,
89 &fops_barrier_nospec);
90 return 0;
91}
92device_initcall(barrier_nospec_debugfs_init);
93#endif /* CONFIG_DEBUG_FS */
94
Michael Ellerman8ad33042018-03-27 23:01:48 +110095ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
96{
Michael Ellermanff348352018-03-27 23:01:49 +110097 bool thread_priv;
98
99 thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV);
100
101 if (rfi_flush || thread_priv) {
102 struct seq_buf s;
103 seq_buf_init(&s, buf, PAGE_SIZE - 1);
104
105 seq_buf_printf(&s, "Mitigation: ");
106
107 if (rfi_flush)
108 seq_buf_printf(&s, "RFI Flush");
109
110 if (rfi_flush && thread_priv)
111 seq_buf_printf(&s, ", ");
112
113 if (thread_priv)
114 seq_buf_printf(&s, "L1D private per thread");
115
116 seq_buf_printf(&s, "\n");
117
118 return s.len;
119 }
120
121 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
122 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
123 return sprintf(buf, "Not affected\n");
Michael Ellerman8ad33042018-03-27 23:01:48 +1100124
125 return sprintf(buf, "Vulnerable\n");
126}
Michael Ellerman56986012018-03-27 23:01:52 +1100127
128ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf)
129{
Michael Ellerman6d44acae2018-07-09 16:25:21 +1000130 struct seq_buf s;
Michael Ellerman56986012018-03-27 23:01:52 +1100131
Michael Ellerman6d44acae2018-07-09 16:25:21 +1000132 seq_buf_init(&s, buf, PAGE_SIZE - 1);
Michal Suchaneka3775142018-05-28 15:19:14 +0200133
Michael Ellerman6d44acae2018-07-09 16:25:21 +1000134 if (security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) {
135 if (barrier_nospec_enabled)
136 seq_buf_printf(&s, "Mitigation: __user pointer sanitization");
137 else
138 seq_buf_printf(&s, "Vulnerable");
139
140 if (security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31))
141 seq_buf_printf(&s, ", ori31 speculation barrier enabled");
142
143 seq_buf_printf(&s, "\n");
144 } else
145 seq_buf_printf(&s, "Not affected\n");
146
147 return s.len;
Michael Ellerman56986012018-03-27 23:01:52 +1100148}
Michael Ellermand6fbe1c2018-03-27 23:01:53 +1100149
150ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf)
151{
Michael Ellermand6fbe1c2018-03-27 23:01:53 +1100152 struct seq_buf s;
Michael Ellerman6d44acae2018-07-09 16:25:21 +1000153 bool bcs, ccd;
Michael Ellermand6fbe1c2018-03-27 23:01:53 +1100154
155 seq_buf_init(&s, buf, PAGE_SIZE - 1);
156
157 bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED);
158 ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED);
Michael Ellermand6fbe1c2018-03-27 23:01:53 +1100159
160 if (bcs || ccd) {
161 seq_buf_printf(&s, "Mitigation: ");
162
163 if (bcs)
164 seq_buf_printf(&s, "Indirect branch serialisation (kernel only)");
165
166 if (bcs && ccd)
167 seq_buf_printf(&s, ", ");
168
169 if (ccd)
170 seq_buf_printf(&s, "Indirect branch cache disabled");
171 } else
172 seq_buf_printf(&s, "Vulnerable");
173
Michael Ellermand6fbe1c2018-03-27 23:01:53 +1100174 seq_buf_printf(&s, "\n");
175
176 return s.len;
177}
Nicholas Piggina048a072018-05-22 09:00:00 +1000178
179/*
180 * Store-forwarding barrier support.
181 */
182
183static enum stf_barrier_type stf_enabled_flush_types;
184static bool no_stf_barrier;
185bool stf_barrier;
186
187static int __init handle_no_stf_barrier(char *p)
188{
189 pr_info("stf-barrier: disabled on command line.");
190 no_stf_barrier = true;
191 return 0;
192}
193
194early_param("no_stf_barrier", handle_no_stf_barrier);
195
196/* This is the generic flag used by other architectures */
197static int __init handle_ssbd(char *p)
198{
199 if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) {
200 /* Until firmware tells us, we have the barrier with auto */
201 return 0;
202 } else if (strncmp(p, "off", 3) == 0) {
203 handle_no_stf_barrier(NULL);
204 return 0;
205 } else
206 return 1;
207
208 return 0;
209}
210early_param("spec_store_bypass_disable", handle_ssbd);
211
212/* This is the generic flag used by other architectures */
213static int __init handle_no_ssbd(char *p)
214{
215 handle_no_stf_barrier(NULL);
216 return 0;
217}
218early_param("nospec_store_bypass_disable", handle_no_ssbd);
219
220static void stf_barrier_enable(bool enable)
221{
222 if (enable)
223 do_stf_barrier_fixups(stf_enabled_flush_types);
224 else
225 do_stf_barrier_fixups(STF_BARRIER_NONE);
226
227 stf_barrier = enable;
228}
229
230void setup_stf_barrier(void)
231{
232 enum stf_barrier_type type;
233 bool enable, hv;
234
235 hv = cpu_has_feature(CPU_FTR_HVMODE);
236
237 /* Default to fallback in case fw-features are not available */
238 if (cpu_has_feature(CPU_FTR_ARCH_300))
239 type = STF_BARRIER_EIEIO;
240 else if (cpu_has_feature(CPU_FTR_ARCH_207S))
241 type = STF_BARRIER_SYNC_ORI;
242 else if (cpu_has_feature(CPU_FTR_ARCH_206))
243 type = STF_BARRIER_FALLBACK;
244 else
245 type = STF_BARRIER_NONE;
246
247 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
248 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) ||
249 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv));
250
251 if (type == STF_BARRIER_FALLBACK) {
252 pr_info("stf-barrier: fallback barrier available\n");
253 } else if (type == STF_BARRIER_SYNC_ORI) {
254 pr_info("stf-barrier: hwsync barrier available\n");
255 } else if (type == STF_BARRIER_EIEIO) {
256 pr_info("stf-barrier: eieio barrier available\n");
257 }
258
259 stf_enabled_flush_types = type;
260
261 if (!no_stf_barrier)
262 stf_barrier_enable(enable);
263}
264
265ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
266{
267 if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) {
268 const char *type;
269 switch (stf_enabled_flush_types) {
270 case STF_BARRIER_EIEIO:
271 type = "eieio";
272 break;
273 case STF_BARRIER_SYNC_ORI:
274 type = "hwsync";
275 break;
276 case STF_BARRIER_FALLBACK:
277 type = "fallback";
278 break;
279 default:
280 type = "unknown";
281 }
282 return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
283 }
284
285 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
286 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
287 return sprintf(buf, "Not affected\n");
288
289 return sprintf(buf, "Vulnerable\n");
290}
291
292#ifdef CONFIG_DEBUG_FS
293static int stf_barrier_set(void *data, u64 val)
294{
295 bool enable;
296
297 if (val == 1)
298 enable = true;
299 else if (val == 0)
300 enable = false;
301 else
302 return -EINVAL;
303
304 /* Only do anything if we're changing state */
305 if (enable != stf_barrier)
306 stf_barrier_enable(enable);
307
308 return 0;
309}
310
311static int stf_barrier_get(void *data, u64 *val)
312{
313 *val = stf_barrier ? 1 : 0;
314 return 0;
315}
316
317DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
318
319static __init int stf_barrier_debugfs_init(void)
320{
321 debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
322 return 0;
323}
324device_initcall(stf_barrier_debugfs_init);
325#endif /* CONFIG_DEBUG_FS */