]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/powerpc/kernel/security.c
powerpc: Move default security feature flags
[mirror_ubuntu-bionic-kernel.git] / arch / powerpc / kernel / security.c
1 // 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>
8 #include <linux/device.h>
9 #include <linux/seq_buf.h>
10
11 #include <asm/debugfs.h>
12 #include <asm/security_features.h>
13
14
15 unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
16
17 ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
18 {
19 bool thread_priv;
20
21 thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV);
22
23 if (rfi_flush || thread_priv) {
24 struct seq_buf s;
25 seq_buf_init(&s, buf, PAGE_SIZE - 1);
26
27 seq_buf_printf(&s, "Mitigation: ");
28
29 if (rfi_flush)
30 seq_buf_printf(&s, "RFI Flush");
31
32 if (rfi_flush && thread_priv)
33 seq_buf_printf(&s, ", ");
34
35 if (thread_priv)
36 seq_buf_printf(&s, "L1D private per thread");
37
38 seq_buf_printf(&s, "\n");
39
40 return s.len;
41 }
42
43 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
44 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
45 return sprintf(buf, "Not affected\n");
46
47 return sprintf(buf, "Vulnerable\n");
48 }
49
50 ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf)
51 {
52 if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR))
53 return sprintf(buf, "Not affected\n");
54
55 return sprintf(buf, "Vulnerable\n");
56 }
57
58 ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf)
59 {
60 bool bcs, ccd, ori;
61 struct seq_buf s;
62
63 seq_buf_init(&s, buf, PAGE_SIZE - 1);
64
65 bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED);
66 ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED);
67 ori = security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31);
68
69 if (bcs || ccd) {
70 seq_buf_printf(&s, "Mitigation: ");
71
72 if (bcs)
73 seq_buf_printf(&s, "Indirect branch serialisation (kernel only)");
74
75 if (bcs && ccd)
76 seq_buf_printf(&s, ", ");
77
78 if (ccd)
79 seq_buf_printf(&s, "Indirect branch cache disabled");
80 } else
81 seq_buf_printf(&s, "Vulnerable");
82
83 if (ori)
84 seq_buf_printf(&s, ", ori31 speculation barrier enabled");
85
86 seq_buf_printf(&s, "\n");
87
88 return s.len;
89 }
90
91 /*
92 * Store-forwarding barrier support.
93 */
94
95 static enum stf_barrier_type stf_enabled_flush_types;
96 static bool no_stf_barrier;
97 bool stf_barrier;
98
99 static int __init handle_no_stf_barrier(char *p)
100 {
101 pr_info("stf-barrier: disabled on command line.");
102 no_stf_barrier = true;
103 return 0;
104 }
105
106 early_param("no_stf_barrier", handle_no_stf_barrier);
107
108 /* This is the generic flag used by other architectures */
109 static int __init handle_ssbd(char *p)
110 {
111 if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) {
112 /* Until firmware tells us, we have the barrier with auto */
113 return 0;
114 } else if (strncmp(p, "off", 3) == 0) {
115 handle_no_stf_barrier(NULL);
116 return 0;
117 } else
118 return 1;
119
120 return 0;
121 }
122 early_param("spec_store_bypass_disable", handle_ssbd);
123
124 /* This is the generic flag used by other architectures */
125 static int __init handle_no_ssbd(char *p)
126 {
127 handle_no_stf_barrier(NULL);
128 return 0;
129 }
130 early_param("nospec_store_bypass_disable", handle_no_ssbd);
131
132 static void stf_barrier_enable(bool enable)
133 {
134 if (enable)
135 do_stf_barrier_fixups(stf_enabled_flush_types);
136 else
137 do_stf_barrier_fixups(STF_BARRIER_NONE);
138
139 stf_barrier = enable;
140 }
141
142 void setup_stf_barrier(void)
143 {
144 enum stf_barrier_type type;
145 bool enable, hv;
146
147 hv = cpu_has_feature(CPU_FTR_HVMODE);
148
149 /* Default to fallback in case fw-features are not available */
150 if (cpu_has_feature(CPU_FTR_ARCH_300))
151 type = STF_BARRIER_EIEIO;
152 else if (cpu_has_feature(CPU_FTR_ARCH_207S))
153 type = STF_BARRIER_SYNC_ORI;
154 else if (cpu_has_feature(CPU_FTR_ARCH_206))
155 type = STF_BARRIER_FALLBACK;
156 else
157 type = STF_BARRIER_NONE;
158
159 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
160 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) ||
161 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv));
162
163 if (type == STF_BARRIER_FALLBACK) {
164 pr_info("stf-barrier: fallback barrier available\n");
165 } else if (type == STF_BARRIER_SYNC_ORI) {
166 pr_info("stf-barrier: hwsync barrier available\n");
167 } else if (type == STF_BARRIER_EIEIO) {
168 pr_info("stf-barrier: eieio barrier available\n");
169 }
170
171 stf_enabled_flush_types = type;
172
173 if (!no_stf_barrier)
174 stf_barrier_enable(enable);
175 }
176
177 ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
178 {
179 if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) {
180 const char *type;
181 switch (stf_enabled_flush_types) {
182 case STF_BARRIER_EIEIO:
183 type = "eieio";
184 break;
185 case STF_BARRIER_SYNC_ORI:
186 type = "hwsync";
187 break;
188 case STF_BARRIER_FALLBACK:
189 type = "fallback";
190 break;
191 default:
192 type = "unknown";
193 }
194 return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
195 }
196
197 if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
198 !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
199 return sprintf(buf, "Not affected\n");
200
201 return sprintf(buf, "Vulnerable\n");
202 }
203
204 #ifdef CONFIG_DEBUG_FS
205 static int stf_barrier_set(void *data, u64 val)
206 {
207 bool enable;
208
209 if (val == 1)
210 enable = true;
211 else if (val == 0)
212 enable = false;
213 else
214 return -EINVAL;
215
216 /* Only do anything if we're changing state */
217 if (enable != stf_barrier)
218 stf_barrier_enable(enable);
219
220 return 0;
221 }
222
223 static int stf_barrier_get(void *data, u64 *val)
224 {
225 *val = stf_barrier ? 1 : 0;
226 return 0;
227 }
228
229 DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
230
231 static __init int stf_barrier_debugfs_init(void)
232 {
233 debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
234 return 0;
235 }
236 device_initcall(stf_barrier_debugfs_init);
237 #endif /* CONFIG_DEBUG_FS */