1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Test that we can't sigreturn to kernel addresses, or to kernel mode.
4   */
5  
6  #define _GNU_SOURCE
7  
8  #include <stdio.h>
9  #include <signal.h>
10  #include <stdlib.h>
11  #include <sys/types.h>
12  #include <sys/wait.h>
13  #include <unistd.h>
14  
15  #include "utils.h"
16  
17  #define MSR_PR (1ul << 14)
18  
19  static volatile unsigned long long sigreturn_addr;
20  static volatile unsigned long long sigreturn_msr_mask;
21  
sigusr1_handler(int signo,siginfo_t * si,void * uc_ptr)22  static void sigusr1_handler(int signo, siginfo_t *si, void *uc_ptr)
23  {
24  	ucontext_t *uc = (ucontext_t *)uc_ptr;
25  
26  	if (sigreturn_addr)
27  		UCONTEXT_NIA(uc) = sigreturn_addr;
28  
29  	if (sigreturn_msr_mask)
30  		UCONTEXT_MSR(uc) &= sigreturn_msr_mask;
31  }
32  
fork_child(void)33  static pid_t fork_child(void)
34  {
35  	pid_t pid;
36  
37  	pid = fork();
38  	if (pid == 0) {
39  		raise(SIGUSR1);
40  		exit(0);
41  	}
42  
43  	return pid;
44  }
45  
expect_segv(pid_t pid)46  static int expect_segv(pid_t pid)
47  {
48  	int child_ret;
49  
50  	waitpid(pid, &child_ret, 0);
51  	FAIL_IF(WIFEXITED(child_ret));
52  	FAIL_IF(!WIFSIGNALED(child_ret));
53  	FAIL_IF(WTERMSIG(child_ret) != 11);
54  
55  	return 0;
56  }
57  
test_sigreturn_kernel(void)58  int test_sigreturn_kernel(void)
59  {
60  	struct sigaction act;
61  	int child_ret, i;
62  	pid_t pid;
63  
64  	act.sa_sigaction = sigusr1_handler;
65  	act.sa_flags = SA_SIGINFO;
66  	sigemptyset(&act.sa_mask);
67  
68  	FAIL_IF(sigaction(SIGUSR1, &act, NULL));
69  
70  	for (i = 0; i < 2; i++) {
71  		// Return to kernel
72  		sigreturn_addr = 0xcull << 60;
73  		pid = fork_child();
74  		expect_segv(pid);
75  
76  		// Return to kernel virtual
77  		sigreturn_addr = 0xc008ull << 48;
78  		pid = fork_child();
79  		expect_segv(pid);
80  
81  		// Return out of range
82  		sigreturn_addr = 0xc010ull << 48;
83  		pid = fork_child();
84  		expect_segv(pid);
85  
86  		// Return to no-man's land, just below PAGE_OFFSET
87  		sigreturn_addr = (0xcull << 60) - (64 * 1024);
88  		pid = fork_child();
89  		expect_segv(pid);
90  
91  		// Return to no-man's land, above TASK_SIZE_4PB
92  		sigreturn_addr = 0x1ull << 52;
93  		pid = fork_child();
94  		expect_segv(pid);
95  
96  		// Return to 0xd space
97  		sigreturn_addr = 0xdull << 60;
98  		pid = fork_child();
99  		expect_segv(pid);
100  
101  		// Return to 0xe space
102  		sigreturn_addr = 0xeull << 60;
103  		pid = fork_child();
104  		expect_segv(pid);
105  
106  		// Return to 0xf space
107  		sigreturn_addr = 0xfull << 60;
108  		pid = fork_child();
109  		expect_segv(pid);
110  
111  		// Attempt to set PR=0 for 2nd loop (should be blocked by kernel)
112  		sigreturn_msr_mask = ~MSR_PR;
113  	}
114  
115  	printf("All children killed as expected\n");
116  
117  	// Don't change address, just MSR, should return to user as normal
118  	sigreturn_addr = 0;
119  	sigreturn_msr_mask = ~MSR_PR;
120  	pid = fork_child();
121  	waitpid(pid, &child_ret, 0);
122  	FAIL_IF(!WIFEXITED(child_ret));
123  	FAIL_IF(WIFSIGNALED(child_ret));
124  	FAIL_IF(WEXITSTATUS(child_ret) != 0);
125  
126  	return 0;
127  }
128  
main(void)129  int main(void)
130  {
131  	return test_harness(test_sigreturn_kernel, "sigreturn_kernel");
132  }
133