]>
Commit | Line | Data |
---|---|---|
5896c8bd MF |
1 | /* Verify longjmp fortify checking does not reject signal stacks. |
2 | ||
3 | Test case mostly written by Paolo Bonzini <pbonzini@redhat.com>. */ | |
a9a04420 UD |
4 | #include <assert.h> |
5 | #include <setjmp.h> | |
6 | #include <signal.h> | |
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
2c41b529 | 9 | #include <string.h> |
a9a04420 UD |
10 | #include <sys/types.h> |
11 | #include <sys/time.h> | |
12 | #include <sys/resource.h> | |
2c41b529 | 13 | #include <unistd.h> |
a9a04420 | 14 | |
14699b6e FW |
15 | static int do_test (void); |
16 | #define TEST_FUNCTION do_test () | |
17 | #include "../test-skeleton.c" | |
a9a04420 UD |
18 | |
19 | static jmp_buf mainloop; | |
20 | static sigset_t mainsigset; | |
2c41b529 | 21 | static volatile sig_atomic_t pass; |
a9a04420 | 22 | |
2c41b529 | 23 | static void |
14699b6e | 24 | write_indented (const char *str) |
2c41b529 | 25 | { |
2c41b529 | 26 | for (int i = 0; i < pass; ++i) |
14699b6e FW |
27 | write_message (" "); |
28 | write_message (str); | |
2c41b529 | 29 | } |
a9a04420 UD |
30 | |
31 | static void | |
32 | stackoverflow_handler (int sig) | |
33 | { | |
34 | stack_t altstack; | |
5896c8bd MF |
35 | /* Sanity check to keep test from looping forever (in case the longjmp |
36 | chk code is slightly broken). */ | |
a9a04420 UD |
37 | pass++; |
38 | sigaltstack (NULL, &altstack); | |
14699b6e | 39 | write_indented ("in signal handler\n"); |
a9a04420 | 40 | if (altstack.ss_flags & SS_ONSTACK) |
14699b6e | 41 | write_indented ("on alternate stack\n"); |
a9a04420 UD |
42 | siglongjmp (mainloop, pass); |
43 | } | |
44 | ||
45 | ||
46 | static volatile int * | |
47 | recurse_1 (int n, volatile int *p) | |
48 | { | |
49 | if (n >= 0) | |
50 | *recurse_1 (n + 1, p) += n; | |
51 | return p; | |
52 | } | |
53 | ||
54 | ||
55 | static int | |
56 | recurse (int n) | |
57 | { | |
58 | int sum = 0; | |
59 | return *recurse_1 (n, &sum); | |
60 | } | |
61 | ||
62 | ||
63 | static int | |
64 | do_test (void) | |
65 | { | |
66 | char mystack[SIGSTKSZ]; | |
67 | stack_t altstack; | |
68 | struct sigaction action; | |
69 | sigset_t emptyset; | |
70 | /* Before starting the endless recursion, try to be friendly to the user's | |
71 | machine. On some Linux 2.2.x systems, there is no stack limit for user | |
72 | processes at all. We don't want to kill such systems. */ | |
73 | struct rlimit rl; | |
74 | rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */ | |
75 | setrlimit (RLIMIT_STACK, &rl); | |
76 | /* Install the alternate stack. */ | |
77 | altstack.ss_sp = mystack; | |
78 | altstack.ss_size = sizeof (mystack); | |
79 | altstack.ss_flags = 0; /* no SS_DISABLE */ | |
80 | if (sigaltstack (&altstack, NULL) < 0) | |
81 | { | |
82 | puts ("first sigaltstack failed"); | |
83 | return 0; | |
84 | } | |
85 | /* Install the SIGSEGV handler. */ | |
86 | sigemptyset (&action.sa_mask); | |
87 | action.sa_handler = &stackoverflow_handler; | |
88 | action.sa_flags = SA_ONSTACK; | |
89 | sigaction (SIGSEGV, &action, (struct sigaction *) NULL); | |
90 | sigaction (SIGBUS, &action, (struct sigaction *) NULL); | |
91 | ||
92 | /* Save the current signal mask. */ | |
93 | sigemptyset (&emptyset); | |
94 | sigprocmask (SIG_BLOCK, &emptyset, &mainsigset); | |
95 | ||
96 | /* Provoke two stack overflows in a row. */ | |
97 | if (sigsetjmp (mainloop, 1) != 0) | |
98 | { | |
99 | assert (pass != 0); | |
100 | printf ("%*sout of signal handler\n", pass, ""); | |
101 | } | |
102 | else | |
103 | assert (pass == 0); | |
104 | ||
105 | sigaltstack (NULL, &altstack); | |
106 | if (altstack.ss_flags & SS_ONSTACK) | |
107 | printf ("%*son alternate stack\n", pass, ""); | |
108 | else | |
109 | printf ("%*snot on alternate stack\n", pass, ""); | |
110 | ||
111 | if (pass < 2) | |
112 | { | |
113 | recurse (0); | |
114 | puts ("recurse call returned"); | |
115 | return 2; | |
116 | } | |
117 | ||
118 | altstack.ss_flags |= SS_DISABLE; | |
119 | if (sigaltstack (&altstack, NULL) == -1) | |
120 | printf ("disabling alternate stack failed\n"); | |
121 | else | |
122 | printf ("disabling alternate stack succeeded \n"); | |
123 | ||
2c41b529 FW |
124 | /* Restore the signal handlers, in case we trigger a crash after the |
125 | tests above. */ | |
126 | signal (SIGBUS, SIG_DFL); | |
127 | signal (SIGSEGV, SIG_DFL); | |
128 | ||
a9a04420 UD |
129 | return 0; |
130 | } |