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