1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2023 ARM Limited.
4 */
5
6 #include <limits.h>
7 #include <stdbool.h>
8
9 #include <linux/prctl.h>
10
11 #include <sys/mman.h>
12 #include <asm/mman.h>
13 #include <linux/sched.h>
14
15 #include "kselftest.h"
16 #include "gcs-util.h"
17
18 /* nolibc doesn't have sysconf(), just hard code the maximum */
19 static size_t page_size = 65536;
20
valid_gcs_function(void)21 static __attribute__((noinline)) void valid_gcs_function(void)
22 {
23 /* Do something the compiler can't optimise out */
24 my_syscall1(__NR_prctl, PR_SVE_GET_VL);
25 }
26
gcs_set_status(unsigned long mode)27 static inline int gcs_set_status(unsigned long mode)
28 {
29 bool enabling = mode & PR_SHADOW_STACK_ENABLE;
30 int ret;
31 unsigned long new_mode;
32
33 /*
34 * The prctl takes 1 argument but we need to ensure that the
35 * other 3 values passed in registers to the syscall are zero
36 * since the kernel validates them.
37 */
38 ret = my_syscall5(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, mode,
39 0, 0, 0);
40
41 if (ret == 0) {
42 ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS,
43 &new_mode, 0, 0, 0);
44 if (ret == 0) {
45 if (new_mode != mode) {
46 ksft_print_msg("Mode set to %lx not %lx\n",
47 new_mode, mode);
48 ret = -EINVAL;
49 }
50 } else {
51 ksft_print_msg("Failed to validate mode: %d\n", ret);
52 }
53
54 if (enabling != chkfeat_gcs()) {
55 ksft_print_msg("%senabled by prctl but %senabled in CHKFEAT\n",
56 enabling ? "" : "not ",
57 chkfeat_gcs() ? "" : "not ");
58 ret = -EINVAL;
59 }
60 }
61
62 return ret;
63 }
64
65 /* Try to read the status */
read_status(void)66 static bool read_status(void)
67 {
68 unsigned long state;
69 int ret;
70
71 ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS,
72 &state, 0, 0, 0);
73 if (ret != 0) {
74 ksft_print_msg("Failed to read state: %d\n", ret);
75 return false;
76 }
77
78 return state & PR_SHADOW_STACK_ENABLE;
79 }
80
81 /* Just a straight enable */
base_enable(void)82 static bool base_enable(void)
83 {
84 int ret;
85
86 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE);
87 if (ret) {
88 ksft_print_msg("PR_SHADOW_STACK_ENABLE failed %d\n", ret);
89 return false;
90 }
91
92 return true;
93 }
94
95 /* Check we can read GCSPR_EL0 when GCS is enabled */
read_gcspr_el0(void)96 static bool read_gcspr_el0(void)
97 {
98 unsigned long *gcspr_el0;
99
100 ksft_print_msg("GET GCSPR\n");
101 gcspr_el0 = get_gcspr();
102 ksft_print_msg("GCSPR_EL0 is %p\n", gcspr_el0);
103
104 return true;
105 }
106
107 /* Also allow writes to stack */
enable_writeable(void)108 static bool enable_writeable(void)
109 {
110 int ret;
111
112 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE);
113 if (ret) {
114 ksft_print_msg("PR_SHADOW_STACK_ENABLE writeable failed: %d\n", ret);
115 return false;
116 }
117
118 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE);
119 if (ret) {
120 ksft_print_msg("failed to restore plain enable %d\n", ret);
121 return false;
122 }
123
124 return true;
125 }
126
127 /* Also allow writes to stack */
enable_push_pop(void)128 static bool enable_push_pop(void)
129 {
130 int ret;
131
132 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH);
133 if (ret) {
134 ksft_print_msg("PR_SHADOW_STACK_ENABLE with push failed: %d\n",
135 ret);
136 return false;
137 }
138
139 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE);
140 if (ret) {
141 ksft_print_msg("failed to restore plain enable %d\n", ret);
142 return false;
143 }
144
145 return true;
146 }
147
148 /* Enable GCS and allow everything */
enable_all(void)149 static bool enable_all(void)
150 {
151 int ret;
152
153 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH |
154 PR_SHADOW_STACK_WRITE);
155 if (ret) {
156 ksft_print_msg("PR_SHADOW_STACK_ENABLE with everything failed: %d\n",
157 ret);
158 return false;
159 }
160
161 ret = gcs_set_status(PR_SHADOW_STACK_ENABLE);
162 if (ret) {
163 ksft_print_msg("failed to restore plain enable %d\n", ret);
164 return false;
165 }
166
167 return true;
168 }
169
enable_invalid(void)170 static bool enable_invalid(void)
171 {
172 int ret = gcs_set_status(ULONG_MAX);
173 if (ret == 0) {
174 ksft_print_msg("GCS_SET_STATUS %lx succeeded\n", ULONG_MAX);
175 return false;
176 }
177
178 return true;
179 }
180
181 /* Map a GCS */
map_guarded_stack(void)182 static bool map_guarded_stack(void)
183 {
184 int ret;
185 uint64_t *buf;
186 uint64_t expected_cap;
187 int elem;
188 bool pass = true;
189
190 buf = (void *)my_syscall3(__NR_map_shadow_stack, 0, page_size,
191 SHADOW_STACK_SET_MARKER |
192 SHADOW_STACK_SET_TOKEN);
193 if (buf == MAP_FAILED) {
194 ksft_print_msg("Failed to map %lu byte GCS: %d\n",
195 page_size, errno);
196 return false;
197 }
198 ksft_print_msg("Mapped GCS at %p-%p\n", buf,
199 (void *)((uint64_t)buf + page_size));
200
201 /* The top of the newly allocated region should be 0 */
202 elem = (page_size / sizeof(uint64_t)) - 1;
203 if (buf[elem]) {
204 ksft_print_msg("Last entry is 0x%llx not 0x0\n", buf[elem]);
205 pass = false;
206 }
207
208 /* Then a valid cap token */
209 elem--;
210 expected_cap = ((uint64_t)buf + page_size - 16);
211 expected_cap &= GCS_CAP_ADDR_MASK;
212 expected_cap |= GCS_CAP_VALID_TOKEN;
213 if (buf[elem] != expected_cap) {
214 ksft_print_msg("Cap entry is 0x%llx not 0x%llx\n",
215 buf[elem], expected_cap);
216 pass = false;
217 }
218 ksft_print_msg("cap token is 0x%llx\n", buf[elem]);
219
220 /* The rest should be zeros */
221 for (elem = 0; elem < page_size / sizeof(uint64_t) - 2; elem++) {
222 if (!buf[elem])
223 continue;
224 ksft_print_msg("GCS slot %d is 0x%llx not 0x0\n",
225 elem, buf[elem]);
226 pass = false;
227 }
228
229 ret = munmap(buf, page_size);
230 if (ret != 0) {
231 ksft_print_msg("Failed to unmap %ld byte GCS: %d\n",
232 page_size, errno);
233 pass = false;
234 }
235
236 return pass;
237 }
238
239 /* A fork()ed process can run */
test_fork(void)240 static bool test_fork(void)
241 {
242 unsigned long child_mode;
243 int ret, status;
244 pid_t pid;
245 bool pass = true;
246
247 pid = fork();
248 if (pid == -1) {
249 ksft_print_msg("fork() failed: %d\n", errno);
250 pass = false;
251 goto out;
252 }
253 if (pid == 0) {
254 /* In child, make sure we can call a function, read
255 * the GCS pointer and status and then exit */
256 valid_gcs_function();
257 get_gcspr();
258
259 ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS,
260 &child_mode, 0, 0, 0);
261 if (ret == 0 && !(child_mode & PR_SHADOW_STACK_ENABLE)) {
262 ksft_print_msg("GCS not enabled in child\n");
263 ret = -EINVAL;
264 }
265
266 exit(ret);
267 }
268
269 /*
270 * In parent, check we can still do function calls then block
271 * for the child.
272 */
273 valid_gcs_function();
274
275 ksft_print_msg("Waiting for child %d\n", pid);
276
277 ret = waitpid(pid, &status, 0);
278 if (ret == -1) {
279 ksft_print_msg("Failed to wait for child: %d\n",
280 errno);
281 return false;
282 }
283
284 if (!WIFEXITED(status)) {
285 ksft_print_msg("Child exited due to signal %d\n",
286 WTERMSIG(status));
287 pass = false;
288 } else {
289 if (WEXITSTATUS(status)) {
290 ksft_print_msg("Child exited with status %d\n",
291 WEXITSTATUS(status));
292 pass = false;
293 }
294 }
295
296 out:
297
298 return pass;
299 }
300
301 typedef bool (*gcs_test)(void);
302
303 static struct {
304 char *name;
305 gcs_test test;
306 bool needs_enable;
307 } tests[] = {
308 { "read_status", read_status },
309 { "base_enable", base_enable, true },
310 { "read_gcspr_el0", read_gcspr_el0 },
311 { "enable_writeable", enable_writeable, true },
312 { "enable_push_pop", enable_push_pop, true },
313 { "enable_all", enable_all, true },
314 { "enable_invalid", enable_invalid, true },
315 { "map_guarded_stack", map_guarded_stack },
316 { "fork", test_fork },
317 };
318
main(void)319 int main(void)
320 {
321 int i, ret;
322 unsigned long gcs_mode;
323
324 ksft_print_header();
325
326 /*
327 * We don't have getauxval() with nolibc so treat a failure to
328 * read GCS state as a lack of support and skip.
329 */
330 ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS,
331 &gcs_mode, 0, 0, 0);
332 if (ret != 0)
333 ksft_exit_skip("Failed to read GCS state: %d\n", ret);
334
335 if (!(gcs_mode & PR_SHADOW_STACK_ENABLE)) {
336 gcs_mode = PR_SHADOW_STACK_ENABLE;
337 ret = my_syscall5(__NR_prctl, PR_SET_SHADOW_STACK_STATUS,
338 gcs_mode, 0, 0, 0);
339 if (ret != 0)
340 ksft_exit_fail_msg("Failed to enable GCS: %d\n", ret);
341 }
342
343 ksft_set_plan(ARRAY_SIZE(tests));
344
345 for (i = 0; i < ARRAY_SIZE(tests); i++) {
346 ksft_test_result((*tests[i].test)(), "%s\n", tests[i].name);
347 }
348
349 /* One last test: disable GCS, we can do this one time */
350 my_syscall5(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, 0, 0, 0, 0);
351 if (ret != 0)
352 ksft_print_msg("Failed to disable GCS: %d\n", ret);
353
354 ksft_finished();
355
356 return 0;
357 }
358