xref: /linux/tools/testing/selftests/riscv/cfi/shadowstack.c (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include "../../kselftest.h"
4 #include <sys/wait.h>
5 #include <signal.h>
6 #include <fcntl.h>
7 #include <asm-generic/unistd.h>
8 #include <sys/mman.h>
9 #include "shadowstack.h"
10 #include "cfi_rv_test.h"
11 
12 static struct shadow_stack_tests shstk_tests[] = {
13 	{ "shstk fork test\n", shadow_stack_fork_test },
14 	{ "map shadow stack syscall\n", shadow_stack_map_test },
15 	{ "shadow stack gup tests\n", shadow_stack_gup_tests },
16 	{ "shadow stack signal tests\n", shadow_stack_signal_test},
17 	{ "memory protections of shadow stack memory\n", shadow_stack_protection_test }
18 };
19 
20 #define RISCV_SHADOW_STACK_TESTS ARRAY_SIZE(shstk_tests)
21 
22 /* do not optimize shadow stack related test functions */
23 #pragma GCC push_options
24 #pragma GCC optimize("O0")
25 
26 void zar(void)
27 {
28 	unsigned long ssp = 0;
29 
30 	ssp = csr_read(CSR_SSP);
31 	ksft_print_msg("Spewing out shadow stack ptr: %lx\n"
32 			"  This is to ensure shadow stack is indeed enabled and working\n",
33 			ssp);
34 }
35 
36 void bar(void)
37 {
38 	zar();
39 }
40 
41 void foo(void)
42 {
43 	bar();
44 }
45 
46 void zar_child(void)
47 {
48 	unsigned long ssp = 0;
49 
50 	ssp = csr_read(CSR_SSP);
51 	ksft_print_msg("Spewing out shadow stack ptr: %lx\n"
52 			"  This is to ensure shadow stack is indeed enabled and working\n",
53 			ssp);
54 }
55 
56 void bar_child(void)
57 {
58 	zar_child();
59 }
60 
61 void foo_child(void)
62 {
63 	bar_child();
64 }
65 
66 typedef void (call_func_ptr)(void);
67 /*
68  * call couple of functions to test push/pop.
69  */
70 int shadow_stack_call_tests(call_func_ptr fn_ptr, bool parent)
71 {
72 	ksft_print_msg("dummy calls for sspush and sspopchk in context of %s\n",
73 		       parent ? "parent" : "child");
74 
75 	(fn_ptr)();
76 
77 	return 0;
78 }
79 
80 /* forks a thread, and ensure shadow stacks fork out */
81 bool shadow_stack_fork_test(unsigned long test_num, void *ctx)
82 {
83 	int pid = 0, child_status = 0, parent_pid = 0, ret = 0;
84 	unsigned long ss_status = 0;
85 
86 	ksft_print_msg("Exercising shadow stack fork test\n");
87 
88 	ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &ss_status, 0, 0, 0);
89 	if (ret) {
90 		ksft_exit_skip("Shadow stack get status prctl failed with errorcode %d\n", ret);
91 		return false;
92 	}
93 
94 	if (!(ss_status & PR_SHADOW_STACK_ENABLE))
95 		ksft_exit_skip("Shadow stack is not enabled, should be enabled via glibc\n");
96 
97 	parent_pid = getpid();
98 	pid = fork();
99 
100 	if (pid) {
101 		ksft_print_msg("Parent pid %d and child pid %d\n", parent_pid, pid);
102 		shadow_stack_call_tests(&foo, true);
103 	} else {
104 		shadow_stack_call_tests(&foo_child, false);
105 	}
106 
107 	if (pid) {
108 		ksft_print_msg("Waiting on child to finish\n");
109 		wait(&child_status);
110 	} else {
111 		/* exit child gracefully */
112 		exit(0);
113 	}
114 
115 	if (pid && WIFSIGNALED(child_status)) {
116 		ksft_print_msg("Child faulted, fork test failed\n");
117 		return false;
118 	}
119 
120 	return true;
121 }
122 
123 /* exercise 'map_shadow_stack', pivot to it and call some functions to ensure it works */
124 #define SHADOW_STACK_ALLOC_SIZE 4096
125 bool shadow_stack_map_test(unsigned long test_num, void *ctx)
126 {
127 	unsigned long shdw_addr;
128 	int ret = 0;
129 
130 	ksft_print_msg("Exercising shadow stack map test\n");
131 
132 	shdw_addr = my_syscall3(__NR_map_shadow_stack, NULL, SHADOW_STACK_ALLOC_SIZE, 0);
133 
134 	if (((long)shdw_addr) <= 0) {
135 		ksft_print_msg("map_shadow_stack failed with error code %d\n",
136 			       (int)shdw_addr);
137 		return false;
138 	}
139 
140 	ret = munmap((void *)shdw_addr, SHADOW_STACK_ALLOC_SIZE);
141 
142 	if (ret) {
143 		ksft_print_msg("munmap failed with error code %d\n", ret);
144 		return false;
145 	}
146 
147 	return true;
148 }
149 
150 /*
151  * shadow stack protection tests. map a shadow stack and
152  * validate all memory protections work on it
153  */
154 bool shadow_stack_protection_test(unsigned long test_num, void *ctx)
155 {
156 	unsigned long shdw_addr;
157 	unsigned long *write_addr = NULL;
158 	int ret = 0, pid = 0, child_status = 0;
159 
160 	ksft_print_msg("Exercising shadow stack protection test (WPT)\n");
161 
162 	shdw_addr = my_syscall3(__NR_map_shadow_stack, NULL, SHADOW_STACK_ALLOC_SIZE, 0);
163 
164 	if (((long)shdw_addr) <= 0) {
165 		ksft_print_msg("map_shadow_stack failed with error code %d\n",
166 			       (int)shdw_addr);
167 		return false;
168 	}
169 
170 	write_addr = (unsigned long *)shdw_addr;
171 	pid = fork();
172 
173 	/* no child was created, return false */
174 	if (pid == -1)
175 		return false;
176 
177 	/*
178 	 * try to perform a store from child on shadow stack memory
179 	 * it should result in SIGSEGV
180 	 */
181 	if (!pid) {
182 		/* below write must lead to SIGSEGV */
183 		*write_addr = 0xdeadbeef;
184 	} else {
185 		wait(&child_status);
186 	}
187 
188 	/* test fail, if 0xdeadbeef present on shadow stack address */
189 	if (*write_addr == 0xdeadbeef) {
190 		ksft_print_msg("Shadow stack WPT failed\n");
191 		return false;
192 	}
193 
194 	/* if child reached here, then fail */
195 	if (!pid) {
196 		ksft_print_msg("Shadow stack WPT failed: child reached unreachable state\n");
197 		return false;
198 	}
199 
200 	/* if child exited via signal handler but not for write on ss */
201 	if (WIFEXITED(child_status) &&
202 	    WEXITSTATUS(child_status) != CHILD_EXIT_CODE_SSWRITE) {
203 		ksft_print_msg("Shadow stack WPT failed: child wasn't signaled for write\n");
204 		return false;
205 	}
206 
207 	ret = munmap(write_addr, SHADOW_STACK_ALLOC_SIZE);
208 	if (ret) {
209 		ksft_print_msg("Shadow stack WPT failed: munmap failed, error code %d\n",
210 			       ret);
211 		return false;
212 	}
213 
214 	return true;
215 }
216 
217 #define SS_MAGIC_WRITE_VAL 0xbeefdead
218 
219 int gup_tests(int mem_fd, unsigned long *shdw_addr)
220 {
221 	unsigned long val = 0;
222 
223 	lseek(mem_fd, (unsigned long)shdw_addr, SEEK_SET);
224 	if (read(mem_fd, &val, sizeof(val)) < 0) {
225 		ksft_print_msg("Reading shadow stack mem via gup failed\n");
226 		return 1;
227 	}
228 
229 	val = SS_MAGIC_WRITE_VAL;
230 	lseek(mem_fd, (unsigned long)shdw_addr, SEEK_SET);
231 	if (write(mem_fd, &val, sizeof(val)) < 0) {
232 		ksft_print_msg("Writing shadow stack mem via gup failed\n");
233 		return 1;
234 	}
235 
236 	if (*shdw_addr != SS_MAGIC_WRITE_VAL) {
237 		ksft_print_msg("GUP write to shadow stack memory failed\n");
238 		return 1;
239 	}
240 
241 	return 0;
242 }
243 
244 bool shadow_stack_gup_tests(unsigned long test_num, void *ctx)
245 {
246 	unsigned long shdw_addr = 0;
247 	unsigned long *write_addr = NULL;
248 	int fd = 0;
249 	bool ret = false;
250 
251 	ksft_print_msg("Exercising shadow stack gup tests\n");
252 	shdw_addr = my_syscall3(__NR_map_shadow_stack, NULL, SHADOW_STACK_ALLOC_SIZE, 0);
253 
254 	if (((long)shdw_addr) <= 0) {
255 		ksft_print_msg("map_shadow_stack failed with error code %d\n", (int)shdw_addr);
256 		return false;
257 	}
258 
259 	write_addr = (unsigned long *)shdw_addr;
260 
261 	fd = open("/proc/self/mem", O_RDWR);
262 	if (fd == -1)
263 		return false;
264 
265 	if (gup_tests(fd, write_addr)) {
266 		ksft_print_msg("gup tests failed\n");
267 		goto out;
268 	}
269 
270 	ret = true;
271 out:
272 	if (shdw_addr && munmap(write_addr, SHADOW_STACK_ALLOC_SIZE)) {
273 		ksft_print_msg("munmap failed with error code %d\n", ret);
274 		ret = false;
275 	}
276 
277 	return ret;
278 }
279 
280 volatile bool break_loop;
281 
282 void sigusr1_handler(int signo)
283 {
284 	break_loop = true;
285 }
286 
287 bool sigusr1_signal_test(void)
288 {
289 	struct sigaction sa = {};
290 
291 	sa.sa_handler = sigusr1_handler;
292 	sa.sa_flags = 0;
293 	sigemptyset(&sa.sa_mask);
294 	if (sigaction(SIGUSR1, &sa, NULL)) {
295 		ksft_print_msg("Registering signal handler for SIGUSR1 failed\n");
296 		return false;
297 	}
298 
299 	return true;
300 }
301 
302 /*
303  * shadow stack signal test. shadow stack must be enabled.
304  * register a signal, fork another thread which is waiting
305  * on signal. Send a signal from parent to child, verify
306  * that signal was received by child. If not test fails
307  */
308 bool shadow_stack_signal_test(unsigned long test_num, void *ctx)
309 {
310 	int pid = 0, child_status = 0, ret = 0;
311 	unsigned long ss_status = 0;
312 
313 	ksft_print_msg("Exercising shadow stack signal test\n");
314 
315 	ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &ss_status, 0, 0, 0);
316 	if (ret) {
317 		ksft_print_msg("Shadow stack get status prctl failed with errorcode %d\n", ret);
318 		return false;
319 	}
320 
321 	if (!(ss_status & PR_SHADOW_STACK_ENABLE))
322 		ksft_print_msg("Shadow stack is not enabled, should be enabled via glibc\n");
323 
324 	/* this should be caught by signal handler and do an exit */
325 	if (!sigusr1_signal_test()) {
326 		ksft_print_msg("Registering sigusr1 handler failed\n");
327 		exit(-1);
328 	}
329 
330 	pid = fork();
331 
332 	if (pid == -1) {
333 		ksft_print_msg("Signal test: fork failed\n");
334 		goto out;
335 	}
336 
337 	if (pid == 0) {
338 		while (!break_loop)
339 			sleep(1);
340 
341 		exit(11);
342 		/* child shouldn't go beyond here */
343 	}
344 
345 	/* send SIGUSR1 to child */
346 	kill(pid, SIGUSR1);
347 	wait(&child_status);
348 
349 out:
350 
351 	return (WIFEXITED(child_status) &&
352 		WEXITSTATUS(child_status) == 11);
353 }
354 
355 int execute_shadow_stack_tests(void)
356 {
357 	int ret = 0;
358 	unsigned long test_count = 0;
359 	unsigned long shstk_status = 0;
360 	bool test_pass = false;
361 
362 	ksft_print_msg("Executing RISC-V shadow stack self tests\n");
363 	ksft_set_plan(RISCV_SHADOW_STACK_TESTS);
364 
365 	ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &shstk_status, 0, 0, 0);
366 
367 	if (ret != 0)
368 		ksft_exit_fail_msg("Get shadow stack status failed with %d\n", ret);
369 
370 	/*
371 	 * If we are here that means get shadow stack status succeeded and
372 	 * thus shadow stack support is baked in the kernel.
373 	 */
374 	while (test_count < RISCV_SHADOW_STACK_TESTS) {
375 		test_pass = (*shstk_tests[test_count].t_func)(test_count, NULL);
376 		ksft_test_result(test_pass, shstk_tests[test_count].name);
377 		test_count++;
378 	}
379 
380 	ksft_finished();
381 
382 	return 0;
383 }
384 
385 #pragma GCC pop_options
386