~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/x86/test_shadow_stack.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * This program test's basic kernel shadow stack support. It enables shadow
  4  * stack manual via the arch_prctl(), instead of relying on glibc. It's
  5  * Makefile doesn't compile with shadow stack support, so it doesn't rely on
  6  * any particular glibc. As a result it can't do any operations that require
  7  * special glibc shadow stack support (longjmp(), swapcontext(), etc). Just
  8  * stick to the basics and hope the compiler doesn't do anything strange.
  9  */
 10 
 11 #define _GNU_SOURCE
 12 
 13 #include <sys/syscall.h>
 14 #include <asm/mman.h>
 15 #include <sys/mman.h>
 16 #include <sys/stat.h>
 17 #include <sys/wait.h>
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 #include <fcntl.h>
 21 #include <unistd.h>
 22 #include <string.h>
 23 #include <errno.h>
 24 #include <stdbool.h>
 25 #include <x86intrin.h>
 26 #include <asm/prctl.h>
 27 #include <sys/prctl.h>
 28 #include <stdint.h>
 29 #include <signal.h>
 30 #include <pthread.h>
 31 #include <sys/ioctl.h>
 32 #include <linux/userfaultfd.h>
 33 #include <setjmp.h>
 34 #include <sys/ptrace.h>
 35 #include <sys/signal.h>
 36 #include <linux/elf.h>
 37 #include <linux/perf_event.h>
 38 
 39 /*
 40  * Define the ABI defines if needed, so people can run the tests
 41  * without building the headers.
 42  */
 43 #ifndef __NR_map_shadow_stack
 44 #define __NR_map_shadow_stack   453
 45 
 46 #define SHADOW_STACK_SET_TOKEN  (1ULL << 0)
 47 
 48 #define ARCH_SHSTK_ENABLE       0x5001
 49 #define ARCH_SHSTK_DISABLE      0x5002
 50 #define ARCH_SHSTK_LOCK         0x5003
 51 #define ARCH_SHSTK_UNLOCK       0x5004
 52 #define ARCH_SHSTK_STATUS       0x5005
 53 
 54 #define ARCH_SHSTK_SHSTK        (1ULL <<  0)
 55 #define ARCH_SHSTK_WRSS         (1ULL <<  1)
 56 
 57 #define NT_X86_SHSTK    0x204
 58 #endif
 59 
 60 #define SS_SIZE 0x200000
 61 #define PAGE_SIZE 0x1000
 62 
 63 #if (__GNUC__ < 8) || (__GNUC__ == 8 && __GNUC_MINOR__ < 5)
 64 int main(int argc, char *argv[])
 65 {
 66         printf("[SKIP]\tCompiler does not support CET.\n");
 67         return 0;
 68 }
 69 #else
 70 void write_shstk(unsigned long *addr, unsigned long val)
 71 {
 72         asm volatile("wrssq %[val], (%[addr])\n"
 73                      : "=m" (addr)
 74                      : [addr] "r" (addr), [val] "r" (val));
 75 }
 76 
 77 static inline unsigned long __attribute__((always_inline)) get_ssp(void)
 78 {
 79         unsigned long ret = 0;
 80 
 81         asm volatile("xor %0, %0; rdsspq %0" : "=r" (ret));
 82         return ret;
 83 }
 84 
 85 /*
 86  * For use in inline enablement of shadow stack.
 87  *
 88  * The program can't return from the point where shadow stack gets enabled
 89  * because there will be no address on the shadow stack. So it can't use
 90  * syscall() for enablement, since it is a function.
 91  *
 92  * Based on code from nolibc.h. Keep a copy here because this can't pull in all
 93  * of nolibc.h.
 94  */
 95 #define ARCH_PRCTL(arg1, arg2)                                  \
 96 ({                                                              \
 97         long _ret;                                              \
 98         register long _num  asm("eax") = __NR_arch_prctl;       \
 99         register long _arg1 asm("rdi") = (long)(arg1);          \
100         register long _arg2 asm("rsi") = (long)(arg2);          \
101                                                                 \
102         asm volatile (                                          \
103                 "syscall\n"                                     \
104                 : "=a"(_ret)                                    \
105                 : "r"(_arg1), "r"(_arg2),                       \
106                   ""(_num)                                     \
107                 : "rcx", "r11", "memory", "cc"                  \
108         );                                                      \
109         _ret;                                                   \
110 })
111 
112 void *create_shstk(void *addr)
113 {
114         return (void *)syscall(__NR_map_shadow_stack, addr, SS_SIZE, SHADOW_STACK_SET_TOKEN);
115 }
116 
117 void *create_normal_mem(void *addr)
118 {
119         return mmap(addr, SS_SIZE, PROT_READ | PROT_WRITE,
120                     MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
121 }
122 
123 void free_shstk(void *shstk)
124 {
125         munmap(shstk, SS_SIZE);
126 }
127 
128 int reset_shstk(void *shstk)
129 {
130         return madvise(shstk, SS_SIZE, MADV_DONTNEED);
131 }
132 
133 void try_shstk(unsigned long new_ssp)
134 {
135         unsigned long ssp;
136 
137         printf("[INFO]\tnew_ssp = %lx, *new_ssp = %lx\n",
138                new_ssp, *((unsigned long *)new_ssp));
139 
140         ssp = get_ssp();
141         printf("[INFO]\tchanging ssp from %lx to %lx\n", ssp, new_ssp);
142 
143         asm volatile("rstorssp (%0)\n":: "r" (new_ssp));
144         asm volatile("saveprevssp");
145         printf("[INFO]\tssp is now %lx\n", get_ssp());
146 
147         /* Switch back to original shadow stack */
148         ssp -= 8;
149         asm volatile("rstorssp (%0)\n":: "r" (ssp));
150         asm volatile("saveprevssp");
151 }
152 
153 int test_shstk_pivot(void)
154 {
155         void *shstk = create_shstk(0);
156 
157         if (shstk == MAP_FAILED) {
158                 printf("[FAIL]\tError creating shadow stack: %d\n", errno);
159                 return 1;
160         }
161         try_shstk((unsigned long)shstk + SS_SIZE - 8);
162         free_shstk(shstk);
163 
164         printf("[OK]\tShadow stack pivot\n");
165         return 0;
166 }
167 
168 int test_shstk_faults(void)
169 {
170         unsigned long *shstk = create_shstk(0);
171 
172         /* Read shadow stack, test if it's zero to not get read optimized out */
173         if (*shstk != 0)
174                 goto err;
175 
176         /* Wrss memory that was already read. */
177         write_shstk(shstk, 1);
178         if (*shstk != 1)
179                 goto err;
180 
181         /* Page out memory, so we can wrss it again. */
182         if (reset_shstk((void *)shstk))
183                 goto err;
184 
185         write_shstk(shstk, 1);
186         if (*shstk != 1)
187                 goto err;
188 
189         printf("[OK]\tShadow stack faults\n");
190         return 0;
191 
192 err:
193         return 1;
194 }
195 
196 unsigned long saved_ssp;
197 unsigned long saved_ssp_val;
198 volatile bool segv_triggered;
199 
200 void __attribute__((noinline)) violate_ss(void)
201 {
202         saved_ssp = get_ssp();
203         saved_ssp_val = *(unsigned long *)saved_ssp;
204 
205         /* Corrupt shadow stack */
206         printf("[INFO]\tCorrupting shadow stack\n");
207         write_shstk((void *)saved_ssp, 0);
208 }
209 
210 void segv_handler(int signum, siginfo_t *si, void *uc)
211 {
212         printf("[INFO]\tGenerated shadow stack violation successfully\n");
213 
214         segv_triggered = true;
215 
216         /* Fix shadow stack */
217         write_shstk((void *)saved_ssp, saved_ssp_val);
218 }
219 
220 int test_shstk_violation(void)
221 {
222         struct sigaction sa = {};
223 
224         sa.sa_sigaction = segv_handler;
225         sa.sa_flags = SA_SIGINFO;
226         if (sigaction(SIGSEGV, &sa, NULL))
227                 return 1;
228 
229         segv_triggered = false;
230 
231         /* Make sure segv_triggered is set before violate_ss() */
232         asm volatile("" : : : "memory");
233 
234         violate_ss();
235 
236         signal(SIGSEGV, SIG_DFL);
237 
238         printf("[OK]\tShadow stack violation test\n");
239 
240         return !segv_triggered;
241 }
242 
243 /* Gup test state */
244 #define MAGIC_VAL 0x12345678
245 bool is_shstk_access;
246 void *shstk_ptr;
247 int fd;
248 
249 void reset_test_shstk(void *addr)
250 {
251         if (shstk_ptr)
252                 free_shstk(shstk_ptr);
253         shstk_ptr = create_shstk(addr);
254 }
255 
256 void test_access_fix_handler(int signum, siginfo_t *si, void *uc)
257 {
258         printf("[INFO]\tViolation from %s\n", is_shstk_access ? "shstk access" : "normal write");
259 
260         segv_triggered = true;
261 
262         /* Fix shadow stack */
263         if (is_shstk_access) {
264                 reset_test_shstk(shstk_ptr);
265                 return;
266         }
267 
268         free_shstk(shstk_ptr);
269         create_normal_mem(shstk_ptr);
270 }
271 
272 bool test_shstk_access(void *ptr)
273 {
274         is_shstk_access = true;
275         segv_triggered = false;
276         write_shstk(ptr, MAGIC_VAL);
277 
278         asm volatile("" : : : "memory");
279 
280         return segv_triggered;
281 }
282 
283 bool test_write_access(void *ptr)
284 {
285         is_shstk_access = false;
286         segv_triggered = false;
287         *(unsigned long *)ptr = MAGIC_VAL;
288 
289         asm volatile("" : : : "memory");
290 
291         return segv_triggered;
292 }
293 
294 bool gup_write(void *ptr)
295 {
296         unsigned long val;
297 
298         lseek(fd, (unsigned long)ptr, SEEK_SET);
299         if (write(fd, &val, sizeof(val)) < 0)
300                 return 1;
301 
302         return 0;
303 }
304 
305 bool gup_read(void *ptr)
306 {
307         unsigned long val;
308 
309         lseek(fd, (unsigned long)ptr, SEEK_SET);
310         if (read(fd, &val, sizeof(val)) < 0)
311                 return 1;
312 
313         return 0;
314 }
315 
316 int test_gup(void)
317 {
318         struct sigaction sa = {};
319         int status;
320         pid_t pid;
321 
322         sa.sa_sigaction = test_access_fix_handler;
323         sa.sa_flags = SA_SIGINFO;
324         if (sigaction(SIGSEGV, &sa, NULL))
325                 return 1;
326 
327         segv_triggered = false;
328 
329         fd = open("/proc/self/mem", O_RDWR);
330         if (fd == -1)
331                 return 1;
332 
333         reset_test_shstk(0);
334         if (gup_read(shstk_ptr))
335                 return 1;
336         if (test_shstk_access(shstk_ptr))
337                 return 1;
338         printf("[INFO]\tGup read -> shstk access success\n");
339 
340         reset_test_shstk(0);
341         if (gup_write(shstk_ptr))
342                 return 1;
343         if (test_shstk_access(shstk_ptr))
344                 return 1;
345         printf("[INFO]\tGup write -> shstk access success\n");
346 
347         reset_test_shstk(0);
348         if (gup_read(shstk_ptr))
349                 return 1;
350         if (!test_write_access(shstk_ptr))
351                 return 1;
352         printf("[INFO]\tGup read -> write access success\n");
353 
354         reset_test_shstk(0);
355         if (gup_write(shstk_ptr))
356                 return 1;
357         if (!test_write_access(shstk_ptr))
358                 return 1;
359         printf("[INFO]\tGup write -> write access success\n");
360 
361         close(fd);
362 
363         /* COW/gup test */
364         reset_test_shstk(0);
365         pid = fork();
366         if (!pid) {
367                 fd = open("/proc/self/mem", O_RDWR);
368                 if (fd == -1)
369                         exit(1);
370 
371                 if (gup_write(shstk_ptr)) {
372                         close(fd);
373                         exit(1);
374                 }
375                 close(fd);
376                 exit(0);
377         }
378         waitpid(pid, &status, 0);
379         if (WEXITSTATUS(status)) {
380                 printf("[FAIL]\tWrite in child failed\n");
381                 return 1;
382         }
383         if (*(unsigned long *)shstk_ptr == MAGIC_VAL) {
384                 printf("[FAIL]\tWrite in child wrote through to shared memory\n");
385                 return 1;
386         }
387 
388         printf("[INFO]\tCow gup write -> write access success\n");
389 
390         free_shstk(shstk_ptr);
391 
392         signal(SIGSEGV, SIG_DFL);
393 
394         printf("[OK]\tShadow gup test\n");
395 
396         return 0;
397 }
398 
399 int test_mprotect(void)
400 {
401         struct sigaction sa = {};
402 
403         sa.sa_sigaction = test_access_fix_handler;
404         sa.sa_flags = SA_SIGINFO;
405         if (sigaction(SIGSEGV, &sa, NULL))
406                 return 1;
407 
408         segv_triggered = false;
409 
410         /* mprotect a shadow stack as read only */
411         reset_test_shstk(0);
412         if (mprotect(shstk_ptr, SS_SIZE, PROT_READ) < 0) {
413                 printf("[FAIL]\tmprotect(PROT_READ) failed\n");
414                 return 1;
415         }
416 
417         /* try to wrss it and fail */
418         if (!test_shstk_access(shstk_ptr)) {
419                 printf("[FAIL]\tShadow stack access to read-only memory succeeded\n");
420                 return 1;
421         }
422 
423         /*
424          * The shadow stack was reset above to resolve the fault, make the new one
425          * read-only.
426          */
427         if (mprotect(shstk_ptr, SS_SIZE, PROT_READ) < 0) {
428                 printf("[FAIL]\tmprotect(PROT_READ) failed\n");
429                 return 1;
430         }
431 
432         /* then back to writable */
433         if (mprotect(shstk_ptr, SS_SIZE, PROT_WRITE | PROT_READ) < 0) {
434                 printf("[FAIL]\tmprotect(PROT_WRITE) failed\n");
435                 return 1;
436         }
437 
438         /* then wrss to it and succeed */
439         if (test_shstk_access(shstk_ptr)) {
440                 printf("[FAIL]\tShadow stack access to mprotect() writable memory failed\n");
441                 return 1;
442         }
443 
444         free_shstk(shstk_ptr);
445 
446         signal(SIGSEGV, SIG_DFL);
447 
448         printf("[OK]\tmprotect() test\n");
449 
450         return 0;
451 }
452 
453 char zero[4096];
454 
455 static void *uffd_thread(void *arg)
456 {
457         struct uffdio_copy req;
458         int uffd = *(int *)arg;
459         struct uffd_msg msg;
460         int ret;
461 
462         while (1) {
463                 ret = read(uffd, &msg, sizeof(msg));
464                 if (ret > 0)
465                         break;
466                 else if (errno == EAGAIN)
467                         continue;
468                 return (void *)1;
469         }
470 
471         req.dst = msg.arg.pagefault.address;
472         req.src = (__u64)zero;
473         req.len = 4096;
474         req.mode = 0;
475 
476         if (ioctl(uffd, UFFDIO_COPY, &req))
477                 return (void *)1;
478 
479         return (void *)0;
480 }
481 
482 int test_userfaultfd(void)
483 {
484         struct uffdio_register uffdio_register;
485         struct uffdio_api uffdio_api;
486         struct sigaction sa = {};
487         pthread_t thread;
488         void *res;
489         int uffd;
490 
491         sa.sa_sigaction = test_access_fix_handler;
492         sa.sa_flags = SA_SIGINFO;
493         if (sigaction(SIGSEGV, &sa, NULL))
494                 return 1;
495 
496         uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
497         if (uffd < 0) {
498                 printf("[SKIP]\tUserfaultfd unavailable.\n");
499                 return 0;
500         }
501 
502         reset_test_shstk(0);
503 
504         uffdio_api.api = UFFD_API;
505         uffdio_api.features = 0;
506         if (ioctl(uffd, UFFDIO_API, &uffdio_api))
507                 goto err;
508 
509         uffdio_register.range.start = (__u64)shstk_ptr;
510         uffdio_register.range.len = 4096;
511         uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
512         if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
513                 goto err;
514 
515         if (pthread_create(&thread, NULL, &uffd_thread, &uffd))
516                 goto err;
517 
518         reset_shstk(shstk_ptr);
519         test_shstk_access(shstk_ptr);
520 
521         if (pthread_join(thread, &res))
522                 goto err;
523 
524         if (test_shstk_access(shstk_ptr))
525                 goto err;
526 
527         free_shstk(shstk_ptr);
528 
529         signal(SIGSEGV, SIG_DFL);
530 
531         if (!res)
532                 printf("[OK]\tUserfaultfd test\n");
533         return !!res;
534 err:
535         free_shstk(shstk_ptr);
536         close(uffd);
537         signal(SIGSEGV, SIG_DFL);
538         return 1;
539 }
540 
541 /* Simple linked list for keeping track of mappings in test_guard_gap() */
542 struct node {
543         struct node *next;
544         void *mapping;
545 };
546 
547 /*
548  * This tests whether mmap will place other mappings in a shadow stack's guard
549  * gap. The steps are:
550  *   1. Finds an empty place by mapping and unmapping something.
551  *   2. Map a shadow stack in the middle of the known empty area.
552  *   3. Map a bunch of PAGE_SIZE mappings. These will use the search down
553  *      direction, filling any gaps until it encounters the shadow stack's
554  *      guard gap.
555  *   4. When a mapping lands below the shadow stack from step 2, then all
556  *      of the above gaps are filled. The search down algorithm will have
557  *      looked at the shadow stack gaps.
558  *   5. See if it landed in the gap.
559  */
560 int test_guard_gap_other_gaps(void)
561 {
562         void *free_area, *shstk, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
563         struct node *head = NULL, *cur;
564 
565         free_area = mmap(0, SS_SIZE * 3, PROT_READ | PROT_WRITE,
566                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
567         munmap(free_area, SS_SIZE * 3);
568 
569         shstk = create_shstk(free_area + SS_SIZE);
570         if (shstk == MAP_FAILED)
571                 return 1;
572 
573         while (test_map > shstk) {
574                 test_map = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE,
575                                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
576                 if (test_map == MAP_FAILED)
577                         return 1;
578                 cur = malloc(sizeof(*cur));
579                 cur->mapping = test_map;
580 
581                 cur->next = head;
582                 head = cur;
583         }
584 
585         while (head) {
586                 cur = head;
587                 head = cur->next;
588                 munmap(cur->mapping, PAGE_SIZE);
589                 free(cur);
590         }
591 
592         free_shstk(shstk);
593 
594         if (shstk - test_map - PAGE_SIZE != PAGE_SIZE)
595                 return 1;
596 
597         printf("[OK]\tGuard gap test, other mapping's gaps\n");
598 
599         return 0;
600 }
601 
602 /* Tests respecting the guard gap of the mapping getting placed */
603 int test_guard_gap_new_mappings_gaps(void)
604 {
605         void *free_area, *shstk_start, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
606         struct node *head = NULL, *cur;
607         int ret = 0;
608 
609         free_area = mmap(0, PAGE_SIZE * 4, PROT_READ | PROT_WRITE,
610                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
611         munmap(free_area, PAGE_SIZE * 4);
612 
613         /* Test letting map_shadow_stack find a free space */
614         shstk_start = mmap(free_area, PAGE_SIZE, PROT_READ | PROT_WRITE,
615                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
616         if (shstk_start == MAP_FAILED || shstk_start != free_area)
617                 return 1;
618 
619         while (test_map > shstk_start) {
620                 test_map = (void *)syscall(__NR_map_shadow_stack, 0, PAGE_SIZE, 0);
621                 if (test_map == MAP_FAILED) {
622                         printf("[INFO]\tmap_shadow_stack MAP_FAILED\n");
623                         ret = 1;
624                         break;
625                 }
626 
627                 cur = malloc(sizeof(*cur));
628                 cur->mapping = test_map;
629 
630                 cur->next = head;
631                 head = cur;
632 
633                 if (test_map == free_area + PAGE_SIZE) {
634                         printf("[INFO]\tNew mapping has other mapping in guard gap!\n");
635                         ret = 1;
636                         break;
637                 }
638         }
639 
640         while (head) {
641                 cur = head;
642                 head = cur->next;
643                 munmap(cur->mapping, PAGE_SIZE);
644                 free(cur);
645         }
646 
647         munmap(shstk_start, PAGE_SIZE);
648 
649         if (!ret)
650                 printf("[OK]\tGuard gap test, placement mapping's gaps\n");
651 
652         return ret;
653 }
654 
655 /*
656  * Too complicated to pull it out of the 32 bit header, but also get the
657  * 64 bit one needed above. Just define a copy here.
658  */
659 #define __NR_compat_sigaction 67
660 
661 /*
662  * Call 32 bit signal handler to get 32 bit signals ABI. Make sure
663  * to push the registers that will get clobbered.
664  */
665 int sigaction32(int signum, const struct sigaction *restrict act,
666                 struct sigaction *restrict oldact)
667 {
668         register long syscall_reg asm("eax") = __NR_compat_sigaction;
669         register long signum_reg asm("ebx") = signum;
670         register long act_reg asm("ecx") = (long)act;
671         register long oldact_reg asm("edx") = (long)oldact;
672         int ret = 0;
673 
674         asm volatile ("int $0x80;"
675                       : "=a"(ret), "=m"(oldact)
676                       : "r"(syscall_reg), "r"(signum_reg), "r"(act_reg),
677                         "r"(oldact_reg)
678                       : "r8", "r9", "r10", "r11"
679                      );
680 
681         return ret;
682 }
683 
684 sigjmp_buf jmp_buffer;
685 
686 void segv_gp_handler(int signum, siginfo_t *si, void *uc)
687 {
688         segv_triggered = true;
689 
690         /*
691          * To work with old glibc, this can't rely on siglongjmp working with
692          * shadow stack enabled, so disable shadow stack before siglongjmp().
693          */
694         ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
695         siglongjmp(jmp_buffer, -1);
696 }
697 
698 /*
699  * Transition to 32 bit mode and check that a #GP triggers a segfault.
700  */
701 int test_32bit(void)
702 {
703         struct sigaction sa = {};
704         struct sigaction *sa32;
705 
706         /* Create sigaction in 32 bit address range */
707         sa32 = mmap(0, 4096, PROT_READ | PROT_WRITE,
708                     MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
709         sa32->sa_flags = SA_SIGINFO;
710 
711         sa.sa_sigaction = segv_gp_handler;
712         sa.sa_flags = SA_SIGINFO;
713         if (sigaction(SIGSEGV, &sa, NULL))
714                 return 1;
715 
716 
717         segv_triggered = false;
718 
719         /* Make sure segv_triggered is set before triggering the #GP */
720         asm volatile("" : : : "memory");
721 
722         /*
723          * Set handler to somewhere in 32 bit address space
724          */
725         sa32->sa_handler = (void *)sa32;
726         if (sigaction32(SIGUSR1, sa32, NULL))
727                 return 1;
728 
729         if (!sigsetjmp(jmp_buffer, 1))
730                 raise(SIGUSR1);
731 
732         if (segv_triggered)
733                 printf("[OK]\t32 bit test\n");
734 
735         return !segv_triggered;
736 }
737 
738 static int parse_uint_from_file(const char *file, const char *fmt)
739 {
740         int err, ret;
741         FILE *f;
742 
743         f = fopen(file, "re");
744         if (!f) {
745                 err = -errno;
746                 printf("failed to open '%s': %d\n", file, err);
747                 return err;
748         }
749         err = fscanf(f, fmt, &ret);
750         if (err != 1) {
751                 err = err == EOF ? -EIO : -errno;
752                 printf("failed to parse '%s': %d\n", file, err);
753                 fclose(f);
754                 return err;
755         }
756         fclose(f);
757         return ret;
758 }
759 
760 static int determine_uprobe_perf_type(void)
761 {
762         const char *file = "/sys/bus/event_source/devices/uprobe/type";
763 
764         return parse_uint_from_file(file, "%d\n");
765 }
766 
767 static int determine_uprobe_retprobe_bit(void)
768 {
769         const char *file = "/sys/bus/event_source/devices/uprobe/format/retprobe";
770 
771         return parse_uint_from_file(file, "config:%d\n");
772 }
773 
774 static ssize_t get_uprobe_offset(const void *addr)
775 {
776         size_t start, end, base;
777         char buf[256];
778         bool found = false;
779         FILE *f;
780 
781         f = fopen("/proc/self/maps", "r");
782         if (!f)
783                 return -errno;
784 
785         while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &base) == 4) {
786                 if (buf[2] == 'x' && (uintptr_t)addr >= start && (uintptr_t)addr < end) {
787                         found = true;
788                         break;
789                 }
790         }
791 
792         fclose(f);
793 
794         if (!found)
795                 return -ESRCH;
796 
797         return (uintptr_t)addr - start + base;
798 }
799 
800 static __attribute__((noinline)) void uretprobe_trigger(void)
801 {
802         asm volatile ("");
803 }
804 
805 /*
806  * This test setups return uprobe, which is sensitive to shadow stack
807  * (crashes without extra fix). After executing the uretprobe we fail
808  * the test if we receive SIGSEGV, no crash means we're good.
809  *
810  * Helper functions above borrowed from bpf selftests.
811  */
812 static int test_uretprobe(void)
813 {
814         const size_t attr_sz = sizeof(struct perf_event_attr);
815         const char *file = "/proc/self/exe";
816         int bit, fd = 0, type, err = 1;
817         struct perf_event_attr attr;
818         struct sigaction sa = {};
819         ssize_t offset;
820 
821         type = determine_uprobe_perf_type();
822         if (type < 0) {
823                 if (type == -ENOENT)
824                         printf("[SKIP]\tUretprobe test, uprobes are not available\n");
825                 return 0;
826         }
827 
828         offset = get_uprobe_offset(uretprobe_trigger);
829         if (offset < 0)
830                 return 1;
831 
832         bit = determine_uprobe_retprobe_bit();
833         if (bit < 0)
834                 return 1;
835 
836         sa.sa_sigaction = segv_gp_handler;
837         sa.sa_flags = SA_SIGINFO;
838         if (sigaction(SIGSEGV, &sa, NULL))
839                 return 1;
840 
841         /* Setup return uprobe through perf event interface. */
842         memset(&attr, 0, attr_sz);
843         attr.size = attr_sz;
844         attr.type = type;
845         attr.config = 1 << bit;
846         attr.config1 = (__u64) (unsigned long) file;
847         attr.config2 = offset;
848 
849         fd = syscall(__NR_perf_event_open, &attr, 0 /* pid */, -1 /* cpu */,
850                      -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
851         if (fd < 0)
852                 goto out;
853 
854         if (sigsetjmp(jmp_buffer, 1))
855                 goto out;
856 
857         ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK);
858 
859         /*
860          * This either segfaults and goes through sigsetjmp above
861          * or succeeds and we're good.
862          */
863         uretprobe_trigger();
864 
865         printf("[OK]\tUretprobe test\n");
866         err = 0;
867 
868 out:
869         ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
870         signal(SIGSEGV, SIG_DFL);
871         if (fd)
872                 close(fd);
873         return err;
874 }
875 
876 void segv_handler_ptrace(int signum, siginfo_t *si, void *uc)
877 {
878         /* The SSP adjustment caused a segfault. */
879         exit(0);
880 }
881 
882 int test_ptrace(void)
883 {
884         unsigned long saved_ssp, ssp = 0;
885         struct sigaction sa= {};
886         struct iovec iov;
887         int status;
888         int pid;
889 
890         iov.iov_base = &ssp;
891         iov.iov_len = sizeof(ssp);
892 
893         pid = fork();
894         if (!pid) {
895                 ssp = get_ssp();
896 
897                 sa.sa_sigaction = segv_handler_ptrace;
898                 sa.sa_flags = SA_SIGINFO;
899                 if (sigaction(SIGSEGV, &sa, NULL))
900                         return 1;
901 
902                 ptrace(PTRACE_TRACEME, NULL, NULL, NULL);
903                 /*
904                  * The parent will tweak the SSP and return from this function
905                  * will #CP.
906                  */
907                 raise(SIGTRAP);
908 
909                 exit(1);
910         }
911 
912         while (waitpid(pid, &status, 0) != -1 && WSTOPSIG(status) != SIGTRAP);
913 
914         if (ptrace(PTRACE_GETREGSET, pid, NT_X86_SHSTK, &iov)) {
915                 printf("[INFO]\tFailed to PTRACE_GETREGS\n");
916                 goto out_kill;
917         }
918 
919         if (!ssp) {
920                 printf("[INFO]\tPtrace child SSP was 0\n");
921                 goto out_kill;
922         }
923 
924         saved_ssp = ssp;
925 
926         iov.iov_len = 0;
927         if (!ptrace(PTRACE_SETREGSET, pid, NT_X86_SHSTK, &iov)) {
928                 printf("[INFO]\tToo small size accepted via PTRACE_SETREGS\n");
929                 goto out_kill;
930         }
931 
932         iov.iov_len = sizeof(ssp) + 1;
933         if (!ptrace(PTRACE_SETREGSET, pid, NT_X86_SHSTK, &iov)) {
934                 printf("[INFO]\tToo large size accepted via PTRACE_SETREGS\n");
935                 goto out_kill;
936         }
937 
938         ssp += 1;
939         if (!ptrace(PTRACE_SETREGSET, pid, NT_X86_SHSTK, &iov)) {
940                 printf("[INFO]\tUnaligned SSP written via PTRACE_SETREGS\n");
941                 goto out_kill;
942         }
943 
944         ssp = 0xFFFFFFFFFFFF0000;
945         if (!ptrace(PTRACE_SETREGSET, pid, NT_X86_SHSTK, &iov)) {
946                 printf("[INFO]\tKernel range SSP written via PTRACE_SETREGS\n");
947                 goto out_kill;
948         }
949 
950         /*
951          * Tweak the SSP so the child with #CP when it resumes and returns
952          * from raise()
953          */
954         ssp = saved_ssp + 8;
955         iov.iov_len = sizeof(ssp);
956         if (ptrace(PTRACE_SETREGSET, pid, NT_X86_SHSTK, &iov)) {
957                 printf("[INFO]\tFailed to PTRACE_SETREGS\n");
958                 goto out_kill;
959         }
960 
961         if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) {
962                 printf("[INFO]\tFailed to PTRACE_DETACH\n");
963                 goto out_kill;
964         }
965 
966         waitpid(pid, &status, 0);
967         if (WEXITSTATUS(status))
968                 return 1;
969 
970         printf("[OK]\tPtrace test\n");
971         return 0;
972 
973 out_kill:
974         kill(pid, SIGKILL);
975         return 1;
976 }
977 
978 int main(int argc, char *argv[])
979 {
980         int ret = 0;
981 
982         if (ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK)) {
983                 printf("[SKIP]\tCould not enable Shadow stack\n");
984                 return 1;
985         }
986 
987         if (ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK)) {
988                 ret = 1;
989                 printf("[FAIL]\tDisabling shadow stack failed\n");
990         }
991 
992         if (ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK)) {
993                 printf("[SKIP]\tCould not re-enable Shadow stack\n");
994                 return 1;
995         }
996 
997         if (ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_WRSS)) {
998                 printf("[SKIP]\tCould not enable WRSS\n");
999                 ret = 1;
1000                 goto out;
1001         }
1002 
1003         /* Should have succeeded if here, but this is a test, so double check. */
1004         if (!get_ssp()) {
1005                 printf("[FAIL]\tShadow stack disabled\n");
1006                 return 1;
1007         }
1008 
1009         if (test_shstk_pivot()) {
1010                 ret = 1;
1011                 printf("[FAIL]\tShadow stack pivot\n");
1012                 goto out;
1013         }
1014 
1015         if (test_shstk_faults()) {
1016                 ret = 1;
1017                 printf("[FAIL]\tShadow stack fault test\n");
1018                 goto out;
1019         }
1020 
1021         if (test_shstk_violation()) {
1022                 ret = 1;
1023                 printf("[FAIL]\tShadow stack violation test\n");
1024                 goto out;
1025         }
1026 
1027         if (test_gup()) {
1028                 ret = 1;
1029                 printf("[FAIL]\tShadow shadow stack gup\n");
1030                 goto out;
1031         }
1032 
1033         if (test_mprotect()) {
1034                 ret = 1;
1035                 printf("[FAIL]\tShadow shadow mprotect test\n");
1036                 goto out;
1037         }
1038 
1039         if (test_userfaultfd()) {
1040                 ret = 1;
1041                 printf("[FAIL]\tUserfaultfd test\n");
1042                 goto out;
1043         }
1044 
1045         if (test_guard_gap_other_gaps()) {
1046                 ret = 1;
1047                 printf("[FAIL]\tGuard gap test, other mappings' gaps\n");
1048                 goto out;
1049         }
1050 
1051         if (test_guard_gap_new_mappings_gaps()) {
1052                 ret = 1;
1053                 printf("[FAIL]\tGuard gap test, placement mapping's gaps\n");
1054                 goto out;
1055         }
1056 
1057         if (test_ptrace()) {
1058                 ret = 1;
1059                 printf("[FAIL]\tptrace test\n");
1060         }
1061 
1062         if (test_32bit()) {
1063                 ret = 1;
1064                 printf("[FAIL]\t32 bit test\n");
1065                 goto out;
1066         }
1067 
1068         if (test_uretprobe()) {
1069                 ret = 1;
1070                 printf("[FAIL]\turetprobe test\n");
1071                 goto out;
1072         }
1073 
1074         return ret;
1075 
1076 out:
1077         /*
1078          * Disable shadow stack before the function returns, or there will be a
1079          * shadow stack violation.
1080          */
1081         if (ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK)) {
1082                 ret = 1;
1083                 printf("[FAIL]\tDisabling shadow stack failed\n");
1084         }
1085 
1086         return ret;
1087 }
1088 #endif
1089 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php