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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 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