1 // SPDX-License-Identifier: GPL-2.0
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.
13 #include <sys/syscall.h>
25 #include <x86intrin.h>
26 #include <asm/prctl.h>
27 #include <sys/prctl.h>
31 #include <sys/ioctl.h>
32 #include <linux/userfaultfd.h>
34 #include <sys/ptrace.h>
35 #include <sys/signal.h>
36 #include <linux/elf.h>
37 #include <linux/perf_event.h>
40 * Define the ABI defines if needed, so people can run the tests
41 * without building the headers.
43 #ifndef __NR_map_shadow_stack
44 #define __NR_map_shadow_stack 453
46 #define SHADOW_STACK_SET_TOKEN (1ULL << 0)
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
54 #define ARCH_SHSTK_SHSTK (1ULL << 0)
55 #define ARCH_SHSTK_WRSS (1ULL << 1)
57 #define NT_X86_SHSTK 0x204
60 #define SS_SIZE 0x200000
61 #define PAGE_SIZE 0x1000
63 #if (__GNUC__ < 8) || (__GNUC__ == 8 && __GNUC_MINOR__ < 5)
64 int main(int argc
, char *argv
[])
66 printf("[SKIP]\tCompiler does not support CET.\n");
70 void write_shstk(unsigned long *addr
, unsigned long val
)
72 asm volatile("wrssq %[val], (%[addr])\n"
74 : [addr
] "r" (addr
), [val
] "r" (val
));
77 static inline unsigned long __attribute__((always_inline
)) get_ssp(void)
79 unsigned long ret
= 0;
81 asm volatile("xor %0, %0; rdsspq %0" : "=r" (ret
));
86 * For use in inline enablement of shadow stack.
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.
92 * Based on code from nolibc.h. Keep a copy here because this can't pull in all
95 #define ARCH_PRCTL(arg1, arg2) \
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); \
105 : "r"(_arg1), "r"(_arg2), \
107 : "rcx", "r11", "memory", "cc" \
112 void *create_shstk(void *addr
)
114 return (void *)syscall(__NR_map_shadow_stack
, addr
, SS_SIZE
, SHADOW_STACK_SET_TOKEN
);
117 void *create_normal_mem(void *addr
)
119 return mmap(addr
, SS_SIZE
, PROT_READ
| PROT_WRITE
,
120 MAP_PRIVATE
| MAP_ANONYMOUS
, 0, 0);
123 void free_shstk(void *shstk
)
125 munmap(shstk
, SS_SIZE
);
128 int reset_shstk(void *shstk
)
130 return madvise(shstk
, SS_SIZE
, MADV_DONTNEED
);
133 void try_shstk(unsigned long new_ssp
)
137 printf("[INFO]\tnew_ssp = %lx, *new_ssp = %lx\n",
138 new_ssp
, *((unsigned long *)new_ssp
));
141 printf("[INFO]\tchanging ssp from %lx to %lx\n", ssp
, new_ssp
);
143 asm volatile("rstorssp (%0)\n":: "r" (new_ssp
));
144 asm volatile("saveprevssp");
145 printf("[INFO]\tssp is now %lx\n", get_ssp());
147 /* Switch back to original shadow stack */
149 asm volatile("rstorssp (%0)\n":: "r" (ssp
));
150 asm volatile("saveprevssp");
153 int test_shstk_pivot(void)
155 void *shstk
= create_shstk(0);
157 if (shstk
== MAP_FAILED
) {
158 printf("[FAIL]\tError creating shadow stack: %d\n", errno
);
161 try_shstk((unsigned long)shstk
+ SS_SIZE
- 8);
164 printf("[OK]\tShadow stack pivot\n");
168 int test_shstk_faults(void)
170 unsigned long *shstk
= create_shstk(0);
172 /* Read shadow stack, test if it's zero to not get read optimized out */
176 /* Wrss memory that was already read. */
177 write_shstk(shstk
, 1);
181 /* Page out memory, so we can wrss it again. */
182 if (reset_shstk((void *)shstk
))
185 write_shstk(shstk
, 1);
189 printf("[OK]\tShadow stack faults\n");
196 unsigned long saved_ssp
;
197 unsigned long saved_ssp_val
;
198 volatile bool segv_triggered
;
200 void __attribute__((noinline
)) violate_ss(void)
202 saved_ssp
= get_ssp();
203 saved_ssp_val
= *(unsigned long *)saved_ssp
;
205 /* Corrupt shadow stack */
206 printf("[INFO]\tCorrupting shadow stack\n");
207 write_shstk((void *)saved_ssp
, 0);
210 void segv_handler(int signum
, siginfo_t
*si
, void *uc
)
212 printf("[INFO]\tGenerated shadow stack violation successfully\n");
214 segv_triggered
= true;
216 /* Fix shadow stack */
217 write_shstk((void *)saved_ssp
, saved_ssp_val
);
220 int test_shstk_violation(void)
222 struct sigaction sa
= {};
224 sa
.sa_sigaction
= segv_handler
;
225 sa
.sa_flags
= SA_SIGINFO
;
226 if (sigaction(SIGSEGV
, &sa
, NULL
))
229 segv_triggered
= false;
231 /* Make sure segv_triggered is set before violate_ss() */
232 asm volatile("" : : : "memory");
236 signal(SIGSEGV
, SIG_DFL
);
238 printf("[OK]\tShadow stack violation test\n");
240 return !segv_triggered
;
244 #define MAGIC_VAL 0x12345678
245 bool is_shstk_access
;
249 void reset_test_shstk(void *addr
)
252 free_shstk(shstk_ptr
);
253 shstk_ptr
= create_shstk(addr
);
256 void test_access_fix_handler(int signum
, siginfo_t
*si
, void *uc
)
258 printf("[INFO]\tViolation from %s\n", is_shstk_access
? "shstk access" : "normal write");
260 segv_triggered
= true;
262 /* Fix shadow stack */
263 if (is_shstk_access
) {
264 reset_test_shstk(shstk_ptr
);
268 free_shstk(shstk_ptr
);
269 create_normal_mem(shstk_ptr
);
272 bool test_shstk_access(void *ptr
)
274 is_shstk_access
= true;
275 segv_triggered
= false;
276 write_shstk(ptr
, MAGIC_VAL
);
278 asm volatile("" : : : "memory");
280 return segv_triggered
;
283 bool test_write_access(void *ptr
)
285 is_shstk_access
= false;
286 segv_triggered
= false;
287 *(unsigned long *)ptr
= MAGIC_VAL
;
289 asm volatile("" : : : "memory");
291 return segv_triggered
;
294 bool gup_write(void *ptr
)
298 lseek(fd
, (unsigned long)ptr
, SEEK_SET
);
299 if (write(fd
, &val
, sizeof(val
)) < 0)
305 bool gup_read(void *ptr
)
309 lseek(fd
, (unsigned long)ptr
, SEEK_SET
);
310 if (read(fd
, &val
, sizeof(val
)) < 0)
318 struct sigaction sa
= {};
322 sa
.sa_sigaction
= test_access_fix_handler
;
323 sa
.sa_flags
= SA_SIGINFO
;
324 if (sigaction(SIGSEGV
, &sa
, NULL
))
327 segv_triggered
= false;
329 fd
= open("/proc/self/mem", O_RDWR
);
334 if (gup_read(shstk_ptr
))
336 if (test_shstk_access(shstk_ptr
))
338 printf("[INFO]\tGup read -> shstk access success\n");
341 if (gup_write(shstk_ptr
))
343 if (test_shstk_access(shstk_ptr
))
345 printf("[INFO]\tGup write -> shstk access success\n");
348 if (gup_read(shstk_ptr
))
350 if (!test_write_access(shstk_ptr
))
352 printf("[INFO]\tGup read -> write access success\n");
355 if (gup_write(shstk_ptr
))
357 if (!test_write_access(shstk_ptr
))
359 printf("[INFO]\tGup write -> write access success\n");
367 fd
= open("/proc/self/mem", O_RDWR
);
371 if (gup_write(shstk_ptr
)) {
378 waitpid(pid
, &status
, 0);
379 if (WEXITSTATUS(status
)) {
380 printf("[FAIL]\tWrite in child failed\n");
383 if (*(unsigned long *)shstk_ptr
== MAGIC_VAL
) {
384 printf("[FAIL]\tWrite in child wrote through to shared memory\n");
388 printf("[INFO]\tCow gup write -> write access success\n");
390 free_shstk(shstk_ptr
);
392 signal(SIGSEGV
, SIG_DFL
);
394 printf("[OK]\tShadow gup test\n");
399 int test_mprotect(void)
401 struct sigaction sa
= {};
403 sa
.sa_sigaction
= test_access_fix_handler
;
404 sa
.sa_flags
= SA_SIGINFO
;
405 if (sigaction(SIGSEGV
, &sa
, NULL
))
408 segv_triggered
= false;
410 /* mprotect a shadow stack as read only */
412 if (mprotect(shstk_ptr
, SS_SIZE
, PROT_READ
) < 0) {
413 printf("[FAIL]\tmprotect(PROT_READ) failed\n");
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");
424 * The shadow stack was reset above to resolve the fault, make the new one
427 if (mprotect(shstk_ptr
, SS_SIZE
, PROT_READ
) < 0) {
428 printf("[FAIL]\tmprotect(PROT_READ) failed\n");
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");
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");
444 free_shstk(shstk_ptr
);
446 signal(SIGSEGV
, SIG_DFL
);
448 printf("[OK]\tmprotect() test\n");
455 static void *uffd_thread(void *arg
)
457 struct uffdio_copy req
;
458 int uffd
= *(int *)arg
;
463 ret
= read(uffd
, &msg
, sizeof(msg
));
466 else if (errno
== EAGAIN
)
471 req
.dst
= msg
.arg
.pagefault
.address
;
472 req
.src
= (__u64
)zero
;
476 if (ioctl(uffd
, UFFDIO_COPY
, &req
))
482 int test_userfaultfd(void)
484 struct uffdio_register uffdio_register
;
485 struct uffdio_api uffdio_api
;
486 struct sigaction sa
= {};
491 sa
.sa_sigaction
= test_access_fix_handler
;
492 sa
.sa_flags
= SA_SIGINFO
;
493 if (sigaction(SIGSEGV
, &sa
, NULL
))
496 uffd
= syscall(__NR_userfaultfd
, O_CLOEXEC
| O_NONBLOCK
);
498 printf("[SKIP]\tUserfaultfd unavailable.\n");
504 uffdio_api
.api
= UFFD_API
;
505 uffdio_api
.features
= 0;
506 if (ioctl(uffd
, UFFDIO_API
, &uffdio_api
))
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
))
515 if (pthread_create(&thread
, NULL
, &uffd_thread
, &uffd
))
518 reset_shstk(shstk_ptr
);
519 test_shstk_access(shstk_ptr
);
521 if (pthread_join(thread
, &res
))
524 if (test_shstk_access(shstk_ptr
))
527 free_shstk(shstk_ptr
);
529 signal(SIGSEGV
, SIG_DFL
);
532 printf("[OK]\tUserfaultfd test\n");
535 free_shstk(shstk_ptr
);
537 signal(SIGSEGV
, SIG_DFL
);
541 /* Simple linked list for keeping track of mappings in test_guard_gap() */
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
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.
560 int test_guard_gap_other_gaps(void)
562 void *free_area
, *shstk
, *test_map
= (void *)0xFFFFFFFFFFFFFFFF;
563 struct node
*head
= NULL
, *cur
;
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);
569 shstk
= create_shstk(free_area
+ SS_SIZE
);
570 if (shstk
== MAP_FAILED
)
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
)
578 cur
= malloc(sizeof(*cur
));
579 cur
->mapping
= test_map
;
588 munmap(cur
->mapping
, PAGE_SIZE
);
594 if (shstk
- test_map
- PAGE_SIZE
!= PAGE_SIZE
)
597 printf("[OK]\tGuard gap test, other mapping's gaps\n");
602 /* Tests respecting the guard gap of the mapping getting placed */
603 int test_guard_gap_new_mappings_gaps(void)
605 void *free_area
, *shstk_start
, *test_map
= (void *)0xFFFFFFFFFFFFFFFF;
606 struct node
*head
= NULL
, *cur
;
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);
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
)
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");
627 cur
= malloc(sizeof(*cur
));
628 cur
->mapping
= test_map
;
633 if (test_map
== free_area
+ PAGE_SIZE
) {
634 printf("[INFO]\tNew mapping has other mapping in guard gap!\n");
643 munmap(cur
->mapping
, PAGE_SIZE
);
647 munmap(shstk_start
, PAGE_SIZE
);
650 printf("[OK]\tGuard gap test, placement mapping's gaps\n");
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.
659 #define __NR_compat_sigaction 67
662 * Call 32 bit signal handler to get 32 bit signals ABI. Make sure
663 * to push the registers that will get clobbered.
665 int sigaction32(int signum
, const struct sigaction
*restrict act
,
666 struct sigaction
*restrict oldact
)
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
;
674 asm volatile ("int $0x80;"
675 : "=a"(ret
), "=m"(oldact
)
676 : "r"(syscall_reg
), "r"(signum_reg
), "r"(act_reg
),
678 : "r8", "r9", "r10", "r11"
684 sigjmp_buf jmp_buffer
;
686 void segv_gp_handler(int signum
, siginfo_t
*si
, void *uc
)
688 segv_triggered
= true;
691 * To work with old glibc, this can't rely on siglongjmp working with
692 * shadow stack enabled, so disable shadow stack before siglongjmp().
694 ARCH_PRCTL(ARCH_SHSTK_DISABLE
, ARCH_SHSTK_SHSTK
);
695 siglongjmp(jmp_buffer
, -1);
699 * Transition to 32 bit mode and check that a #GP triggers a segfault.
703 struct sigaction sa
= {};
704 struct sigaction
*sa32
;
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
;
711 sa
.sa_sigaction
= segv_gp_handler
;
712 sa
.sa_flags
= SA_SIGINFO
;
713 if (sigaction(SIGSEGV
, &sa
, NULL
))
717 segv_triggered
= false;
719 /* Make sure segv_triggered is set before triggering the #GP */
720 asm volatile("" : : : "memory");
723 * Set handler to somewhere in 32 bit address space
725 sa32
->sa_handler
= (void *)sa32
;
726 if (sigaction32(SIGUSR1
, sa32
, NULL
))
729 if (!sigsetjmp(jmp_buffer
, 1))
733 printf("[OK]\t32 bit test\n");
735 return !segv_triggered
;
738 static int parse_uint_from_file(const char *file
, const char *fmt
)
743 f
= fopen(file
, "re");
746 printf("failed to open '%s': %d\n", file
, err
);
749 err
= fscanf(f
, fmt
, &ret
);
751 err
= err
== EOF
? -EIO
: -errno
;
752 printf("failed to parse '%s': %d\n", file
, err
);
760 static int determine_uprobe_perf_type(void)
762 const char *file
= "/sys/bus/event_source/devices/uprobe/type";
764 return parse_uint_from_file(file
, "%d\n");
767 static int determine_uprobe_retprobe_bit(void)
769 const char *file
= "/sys/bus/event_source/devices/uprobe/format/retprobe";
771 return parse_uint_from_file(file
, "config:%d\n");
774 static ssize_t
get_uprobe_offset(const void *addr
)
776 size_t start
, end
, base
;
781 f
= fopen("/proc/self/maps", "r");
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
) {
797 return (uintptr_t)addr
- start
+ base
;
800 static __attribute__((noinline
)) void uretprobe_trigger(void)
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.
810 * Helper functions above borrowed from bpf selftests.
812 static int test_uretprobe(void)
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
= {};
821 type
= determine_uprobe_perf_type();
824 printf("[SKIP]\tUretprobe test, uprobes are not available\n");
828 offset
= get_uprobe_offset(uretprobe_trigger
);
832 bit
= determine_uprobe_retprobe_bit();
836 sa
.sa_sigaction
= segv_gp_handler
;
837 sa
.sa_flags
= SA_SIGINFO
;
838 if (sigaction(SIGSEGV
, &sa
, NULL
))
841 /* Setup return uprobe through perf event interface. */
842 memset(&attr
, 0, attr_sz
);
845 attr
.config
= 1 << bit
;
846 attr
.config1
= (__u64
) (unsigned long) file
;
847 attr
.config2
= offset
;
849 fd
= syscall(__NR_perf_event_open
, &attr
, 0 /* pid */, -1 /* cpu */,
850 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC
);
854 if (sigsetjmp(jmp_buffer
, 1))
857 ARCH_PRCTL(ARCH_SHSTK_ENABLE
, ARCH_SHSTK_SHSTK
);
860 * This either segfaults and goes through sigsetjmp above
861 * or succeeds and we're good.
865 printf("[OK]\tUretprobe test\n");
869 ARCH_PRCTL(ARCH_SHSTK_DISABLE
, ARCH_SHSTK_SHSTK
);
870 signal(SIGSEGV
, SIG_DFL
);
876 void segv_handler_ptrace(int signum
, siginfo_t
*si
, void *uc
)
878 /* The SSP adjustment caused a segfault. */
882 int test_ptrace(void)
884 unsigned long saved_ssp
, ssp
= 0;
885 struct sigaction sa
= {};
891 iov
.iov_len
= sizeof(ssp
);
897 sa
.sa_sigaction
= segv_handler_ptrace
;
898 sa
.sa_flags
= SA_SIGINFO
;
899 if (sigaction(SIGSEGV
, &sa
, NULL
))
902 ptrace(PTRACE_TRACEME
, NULL
, NULL
, NULL
);
904 * The parent will tweak the SSP and return from this function
912 while (waitpid(pid
, &status
, 0) != -1 && WSTOPSIG(status
) != SIGTRAP
);
914 if (ptrace(PTRACE_GETREGSET
, pid
, NT_X86_SHSTK
, &iov
)) {
915 printf("[INFO]\tFailed to PTRACE_GETREGS\n");
920 printf("[INFO]\tPtrace child SSP was 0\n");
927 if (!ptrace(PTRACE_SETREGSET
, pid
, NT_X86_SHSTK
, &iov
)) {
928 printf("[INFO]\tToo small size accepted via PTRACE_SETREGS\n");
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");
939 if (!ptrace(PTRACE_SETREGSET
, pid
, NT_X86_SHSTK
, &iov
)) {
940 printf("[INFO]\tUnaligned SSP written via PTRACE_SETREGS\n");
944 ssp
= 0xFFFFFFFFFFFF0000;
945 if (!ptrace(PTRACE_SETREGSET
, pid
, NT_X86_SHSTK
, &iov
)) {
946 printf("[INFO]\tKernel range SSP written via PTRACE_SETREGS\n");
951 * Tweak the SSP so the child with #CP when it resumes and returns
955 iov
.iov_len
= sizeof(ssp
);
956 if (ptrace(PTRACE_SETREGSET
, pid
, NT_X86_SHSTK
, &iov
)) {
957 printf("[INFO]\tFailed to PTRACE_SETREGS\n");
961 if (ptrace(PTRACE_DETACH
, pid
, NULL
, NULL
)) {
962 printf("[INFO]\tFailed to PTRACE_DETACH\n");
966 waitpid(pid
, &status
, 0);
967 if (WEXITSTATUS(status
))
970 printf("[OK]\tPtrace test\n");
978 int main(int argc
, char *argv
[])
982 if (ARCH_PRCTL(ARCH_SHSTK_ENABLE
, ARCH_SHSTK_SHSTK
)) {
983 printf("[SKIP]\tCould not enable Shadow stack\n");
987 if (ARCH_PRCTL(ARCH_SHSTK_DISABLE
, ARCH_SHSTK_SHSTK
)) {
989 printf("[FAIL]\tDisabling shadow stack failed\n");
992 if (ARCH_PRCTL(ARCH_SHSTK_ENABLE
, ARCH_SHSTK_SHSTK
)) {
993 printf("[SKIP]\tCould not re-enable Shadow stack\n");
997 if (ARCH_PRCTL(ARCH_SHSTK_ENABLE
, ARCH_SHSTK_WRSS
)) {
998 printf("[SKIP]\tCould not enable WRSS\n");
1003 /* Should have succeeded if here, but this is a test, so double check. */
1005 printf("[FAIL]\tShadow stack disabled\n");
1009 if (test_shstk_pivot()) {
1011 printf("[FAIL]\tShadow stack pivot\n");
1015 if (test_shstk_faults()) {
1017 printf("[FAIL]\tShadow stack fault test\n");
1021 if (test_shstk_violation()) {
1023 printf("[FAIL]\tShadow stack violation test\n");
1029 printf("[FAIL]\tShadow shadow stack gup\n");
1033 if (test_mprotect()) {
1035 printf("[FAIL]\tShadow shadow mprotect test\n");
1039 if (test_userfaultfd()) {
1041 printf("[FAIL]\tUserfaultfd test\n");
1045 if (test_guard_gap_other_gaps()) {
1047 printf("[FAIL]\tGuard gap test, other mappings' gaps\n");
1051 if (test_guard_gap_new_mappings_gaps()) {
1053 printf("[FAIL]\tGuard gap test, placement mapping's gaps\n");
1057 if (test_ptrace()) {
1059 printf("[FAIL]\tptrace test\n");
1064 printf("[FAIL]\t32 bit test\n");
1068 if (test_uretprobe()) {
1070 printf("[FAIL]\turetprobe test\n");
1078 * Disable shadow stack before the function returns, or there will be a
1079 * shadow stack violation.
1081 if (ARCH_PRCTL(ARCH_SHSTK_DISABLE
, ARCH_SHSTK_SHSTK
)) {
1083 printf("[FAIL]\tDisabling shadow stack failed\n");