This source file includes following definitions.
- stackoverflow_handler_continuation
- stackoverflow_handler
- sigsegv_handler
- recurse_1
- recurse
- main
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "sigsegv.h"
23
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <limits.h>
27
28 #if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGSEGV_RECOVERY
29
30 # if defined _WIN32 && !defined __CYGWIN__
31
32 typedef int sigset_t;
33 # define sigemptyset(set)
34 # define sigprocmask(how,set,oldset)
35 # endif
36
37 # include "mmap-anon-util.h"
38 # include <stddef.h>
39 # include <stdlib.h>
40 # include <signal.h>
41 # include <setjmp.h>
42 # if HAVE_SETRLIMIT
43 # include <sys/types.h>
44 # include <sys/time.h>
45 # include <sys/resource.h>
46 # endif
47 # include "altstack-util.h"
48
49 static jmp_buf mainloop;
50 static sigset_t mainsigset;
51
52 static volatile int pass = 0;
53 static uintptr_t page;
54 static volatile int *null_pointer_to_volatile_int ;
55
56 static void
57 stackoverflow_handler_continuation (void *arg1, void *arg2, void *arg3)
58 {
59 int arg = (int) (long) arg1;
60 longjmp (mainloop, arg);
61 }
62
63 static void
64 stackoverflow_handler (int emergency, stackoverflow_context_t scp)
65 {
66 pass++;
67 if (pass <= 2)
68 printf ("Stack overflow %d caught.\n", pass);
69 else
70 {
71 printf ("Segmentation violation misdetected as stack overflow.\n");
72 exit (1);
73 }
74 sigprocmask (SIG_SETMASK, &mainsigset, NULL);
75 sigsegv_leave_handler (stackoverflow_handler_continuation,
76 (void *) (long) (emergency ? -1 : pass), NULL, NULL);
77 }
78
79 static int
80 sigsegv_handler (void *address, int emergency)
81 {
82
83 if (!emergency)
84 return 0;
85
86 pass++;
87 if (pass <= 2)
88 {
89 printf ("Stack overflow %d missed.\n", pass);
90 exit (1);
91 }
92 else
93 printf ("Segmentation violation correctly detected.\n");
94 sigprocmask (SIG_SETMASK, &mainsigset, NULL);
95 return sigsegv_leave_handler (stackoverflow_handler_continuation,
96 (void *) (long) pass, NULL, NULL);
97 }
98
99 static volatile int *
100 recurse_1 (int n, volatile int *p)
101 {
102 if (n < INT_MAX)
103 *recurse_1 (n + 1, p) += n;
104 return p;
105 }
106
107 static int
108 recurse (volatile int n)
109 {
110 return *recurse_1 (n, &n);
111 }
112
113 int
114 main ()
115 {
116 int prot_unwritable;
117 void *p;
118 sigset_t emptyset;
119
120 # if HAVE_SETRLIMIT && defined RLIMIT_STACK
121
122
123
124 struct rlimit rl;
125 rl.rlim_cur = rl.rlim_max = 0x100000;
126 setrlimit (RLIMIT_STACK, &rl);
127 # endif
128
129
130 prepare_alternate_stack ();
131
132
133 if (stackoverflow_install_handler (&stackoverflow_handler,
134 mystack, MYSTACK_SIZE)
135 < 0)
136 exit (2);
137
138
139 # if !HAVE_MAP_ANONYMOUS
140 zero_fd = open ("/dev/zero", O_RDONLY, 0644);
141 # endif
142
143 # if defined __linux__ && defined __sparc__
144
145
146 prot_unwritable = PROT_NONE;
147 # else
148 prot_unwritable = PROT_READ;
149 # endif
150
151
152 p = mmap_zeromap ((void *) 0x12340000, 0x4000);
153 if (p == (void *)(-1))
154 {
155 fprintf (stderr, "mmap_zeromap failed.\n");
156 exit (2);
157 }
158 page = (uintptr_t) p;
159
160
161 if (mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
162 {
163 fprintf (stderr, "mprotect failed.\n");
164 exit (2);
165 }
166
167
168 if (sigsegv_install_handler (&sigsegv_handler) < 0)
169 exit (2);
170
171
172 sigemptyset (&emptyset);
173 sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
174
175
176 switch (setjmp (mainloop))
177 {
178 case -1:
179 printf ("emergency exit\n"); exit (1);
180 case 0: case 1:
181 printf ("Starting recursion pass %d.\n", pass + 1);
182 recurse (0);
183 printf ("no endless recursion?!\n"); exit (1);
184 case 2:
185 *(volatile int *) (page + 0x678) = 42;
186 break;
187 case 3:
188 *null_pointer_to_volatile_int = 42;
189 break;
190 case 4:
191 break;
192 default:
193 abort ();
194 }
195
196
197 check_alternate_stack_no_overflow ();
198
199 printf ("Test passed.\n");
200 exit (0);
201 }
202
203 #else
204
205 int
206 main ()
207 {
208 return 77;
209 }
210
211 #endif