1 /* Fault handler information. Unix version.
2 Copyright (C) 1993-1999, 2002-2003 Bruno Haible <bruno@clisp.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* On the average Unix platform, we define
23 if there is a fault-*.h include file which defines
24 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
26 HAVE_STACK_OVERFLOW_RECOVERY
27 if HAVE_SIGALTSTACK is set and
28 at least two of the following are true:
29 A) There is a fault-*.h include file which defines
30 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
31 B) There is a fault-*.h include file which defines
32 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_STACKPOINTER.
33 C) There is a stackvma-*.c, other than stackvma-none.c, which
34 defines sigsegv_get_vma.
36 Why? Obviously, to catch stack overflow, we need an alternate signal
37 stack; this requires kernel support. But we also need to distinguish
38 (with a reasonable confidence) a stack overflow from a regular SIGSEGV.
39 If we have A) and B), we use the
40 Heuristic AB: If the fault address is near the stack pointer, it's a
42 If we have A) and C), we use the
43 Heuristic AC: If the fault address is near and beyond the bottom of
44 the stack's virtual memory area, it's a stack overflow.
45 If we have B) and C), we use the
46 Heuristic BC: If the stack pointer is near the bottom of the stack's
47 virtual memory area, it's a stack overflow.
48 This heuristic comes in two flavours: On OSes which let the stack's
49 VMA grow continuously, we determine the bottom by use of getrlimit().
50 On OSes which preallocate the stack's VMA with its maximum size
51 (like BeOS), we use the stack's VMA directly.
54 #include <stddef.h> /* needed for NULL on SunOS4 */
58 # include <sys/signal.h>
64 #define SS_DISABLE SA_DISABLE
70 #if HAVE_STACK_OVERFLOW_RECOVERY
72 #include <stdio.h> /* perror */
75 # include <sys/types.h>
76 # include <sys/time.h>
77 # include <sys/resource.h> /* declares struct rlimit */
80 /* Platform dependent:
81 Determine the virtual memory area of a given address. */
84 /* Platform dependent:
85 Leaving a signal handler executing on the alternate stack. */
90 /* Address of the last byte belonging to the stack vma. */
91 static unsigned long stack_top
= 0;
93 /* Needs to be called once only. */
95 remember_stack_top (void *some_variable_on_stack
)
97 struct vma_struct vma
;
99 if (sigsegv_get_vma ((unsigned long) some_variable_on_stack
, &vma
) >= 0)
100 stack_top
= vma
.end
- 1;
103 #endif /* HAVE_STACKVMA */
105 static stackoverflow_handler_t stk_user_handler
= (stackoverflow_handler_t
)NULL
;
106 static unsigned long stk_extra_stack
;
107 static unsigned long stk_extra_stack_size
;
109 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
111 #if HAVE_SIGSEGV_RECOVERY
113 /* User's SIGSEGV handler. */
114 static sigsegv_handler_t user_handler
= (sigsegv_handler_t
)NULL
;
116 #endif /* HAVE_SIGSEGV_RECOVERY */
119 /* Our SIGSEGV handler, with OS dependent argument list. */
121 #if HAVE_SIGSEGV_RECOVERY
124 sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST
)
126 void *address
= (void *) (SIGSEGV_FAULT_ADDRESS
);
128 #if HAVE_STACK_OVERFLOW_RECOVERY
129 #if !(HAVE_STACKVMA || defined SIGSEGV_FAULT_STACKPOINTER)
130 #error "Insufficient heuristics for detecting a stack overflow. Either define CFG_STACKVMA and HAVE_STACKVMA correctly, or define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
133 /* Call user's handler. */
134 if (user_handler
&& (*user_handler
) (address
, 0))
136 /* Handler successful. */
140 /* Handler declined responsibility. */
142 /* Did the user install a stack overflow handler? */
143 if (stk_user_handler
)
145 /* See whether it was a stack overflow. If so, longjump away. */
146 #ifdef SIGSEGV_FAULT_STACKPOINTER
147 unsigned long old_sp
= (unsigned long) (SIGSEGV_FAULT_STACKPOINTER
);
149 unsigned long old_bsp
= (unsigned long) (SIGSEGV_FAULT_BSP_POINTER
);
154 /* Were we able to determine the stack top? */
157 /* Determine stack bounds. */
158 struct vma_struct vma
;
160 if (sigsegv_get_vma (stack_top
, &vma
) >= 0)
162 /* Heuristic AC: If the fault_address is nearer to the stack
163 segment's [start,end] than to the previous segment, we
164 consider it a stack overflow.
165 In the case of IA-64, we know that the previous segment
166 is the up-growing bsp segment, and either of the two
167 stacks can overflow. */
168 unsigned long addr
= (unsigned long) address
;
171 if (addr
>= vma
.prev_end
&& addr
<= vma
.end
- 1)
173 #if STACK_DIRECTION < 0
174 if (addr
>= vma
.start
175 ? (addr
<= vma
.end
- 1)
176 : vma
.is_near_this (addr
, &vma
))
178 if (addr
<= vma
.end
- 1
179 ? (addr
>= vma
.start
)
180 : vma
.is_near_this (addr
, &vma
))
184 /* Heuristic AB: If the fault address is near the stack pointer,
185 it's a stack overflow. */
186 unsigned long addr
= (unsigned long) address
;
188 if ((addr
<= old_sp
+ 4096 && old_sp
<= addr
+ 4096)
190 || (addr
<= old_bsp
+ 4096 && old_bsp
<= addr
+ 4096)
197 #ifdef SIGSEGV_FAULT_STACKPOINTER
199 (old_sp
>= stk_extra_stack
200 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
);
201 stackoverflow_context_t context
= (SIGSEGV_FAULT_CONTEXT
);
204 stackoverflow_context_t context
= (void *) 0;
206 /* Call user's handler. */
207 (*stk_user_handler
) (emergency
, context
);
212 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
214 if (user_handler
&& (*user_handler
) (address
, 1))
216 /* Handler successful. */
220 /* Handler declined responsibility for real. */
222 /* Remove ourselves and dump core. */
223 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
226 #if HAVE_STACK_OVERFLOW_RECOVERY
228 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
231 #elif HAVE_STACK_OVERFLOW_RECOVERY
234 #ifdef SIGSEGV_FAULT_STACKPOINTER
235 sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST
)
237 sigsegv_handler (int sig
)
240 #if !((HAVE_GETRLIMIT && defined RLIMIT_STACK) || defined SIGSEGV_FAULT_STACKPOINTER)
241 #error "Insufficient heuristics for detecting a stack overflow. Either define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
244 /* Did the user install a handler? */
245 if (stk_user_handler
)
247 /* See whether it was a stack overflow. If so, longjump away. */
248 #ifdef SIGSEGV_FAULT_STACKPOINTER
249 unsigned long old_sp
= (unsigned long) (SIGSEGV_FAULT_STACKPOINTER
);
252 /* Were we able to determine the stack top? */
255 /* Determine stack bounds. */
256 struct vma_struct vma
;
258 if (sigsegv_get_vma (stack_top
, &vma
) >= 0)
260 #if HAVE_GETRLIMIT && defined RLIMIT_STACK
261 /* Heuristic BC: If the stack size has reached its maximal size,
262 and old_sp is near the low end, we consider it a stack
266 if (getrlimit (RLIMIT_STACK
, &rl
) >= 0)
268 unsigned long current_stack_size
= vma
.end
- vma
.start
;
269 unsigned long max_stack_size
= rl
.rlim_cur
;
270 if (current_stack_size
<= max_stack_size
+ 4096
271 && max_stack_size
<= current_stack_size
+ 4096
276 #ifdef SIGSEGV_FAULT_STACKPOINTER
277 /* Heuristic BC: If we know old_sp, and it is neither
278 near the low end, nor in the alternate stack, then
279 it's probably not a stack overflow. */
280 && ((old_sp
>= stk_extra_stack
281 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
)
282 #if STACK_DIRECTION < 0
283 || (old_sp
<= vma
.start
+ 4096
284 && vma
.start
<= old_sp
+ 4096))
286 || (old_sp
<= vma
.end
+ 4096
287 && vma
.end
<= old_sp
+ 4096))
292 #ifdef SIGSEGV_FAULT_STACKPOINTER
294 (old_sp
>= stk_extra_stack
295 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
);
296 stackoverflow_context_t context
= (SIGSEGV_FAULT_CONTEXT
);
299 stackoverflow_context_t context
= (void *) 0;
301 /* Call user's handler. */
302 (*stk_user_handler
)(emergency
,context
);
309 /* Remove ourselves and dump core. */
310 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
317 install_for (int sig
)
319 struct sigaction action
;
321 #ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
322 action
.sa_sigaction
= &sigsegv_handler
;
324 action
.sa_handler
= (void (*) (int)) &sigsegv_handler
;
326 /* Block most signals while SIGSEGV is being handled. */
327 /* Signals SIGKILL, SIGSTOP cannot be blocked. */
328 /* Signals SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU are not blocked because
329 dealing with these signals seems dangerous. */
330 /* Signals SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTRAP, SIGIOT, SIGEMT, SIGBUS,
331 SIGSYS, SIGSTKFLT are not blocked because these are synchronous signals,
332 which may require immediate intervention, otherwise the process may
334 sigemptyset (&action
.sa_mask
);
336 sigaddset (&action
.sa_mask
,SIGHUP
);
339 sigaddset (&action
.sa_mask
,SIGINT
);
342 sigaddset (&action
.sa_mask
,SIGQUIT
);
345 sigaddset (&action
.sa_mask
,SIGPIPE
);
348 sigaddset (&action
.sa_mask
,SIGALRM
);
351 sigaddset (&action
.sa_mask
,SIGTERM
);
354 sigaddset (&action
.sa_mask
,SIGUSR1
);
357 sigaddset (&action
.sa_mask
,SIGUSR2
);
360 sigaddset (&action
.sa_mask
,SIGCHLD
);
363 sigaddset (&action
.sa_mask
,SIGCLD
);
366 sigaddset (&action
.sa_mask
,SIGURG
);
369 sigaddset (&action
.sa_mask
,SIGIO
);
372 sigaddset (&action
.sa_mask
,SIGPOLL
);
375 sigaddset (&action
.sa_mask
,SIGXCPU
);
378 sigaddset (&action
.sa_mask
,SIGXFSZ
);
381 sigaddset (&action
.sa_mask
,SIGVTALRM
);
384 sigaddset (&action
.sa_mask
,SIGPROF
);
387 sigaddset (&action
.sa_mask
,SIGPWR
);
390 sigaddset (&action
.sa_mask
,SIGLOST
);
393 sigaddset (&action
.sa_mask
,SIGWINCH
);
395 /* Note that sigaction() implicitly adds sig itself to action.sa_mask. */
396 /* Ask the OS to provide a structure siginfo_t to the handler. */
397 #ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
398 action
.sa_flags
= SA_SIGINFO
;
402 #if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGALTSTACK /* not BeOS */
403 /* Work around Linux 2.2.5 bug: If SA_ONSTACK is specified but sigaltstack()
404 has not been called, the kernel will busy loop, eating CPU time. So
405 avoid setting SA_ONSTACK until the user has requested stack overflow
407 if (stk_user_handler
)
408 action
.sa_flags
|= SA_ONSTACK
;
410 sigaction (sig
, &action
, (struct sigaction
*) NULL
);
414 sigsegv_install_handler (sigsegv_handler_t handler
)
416 #if HAVE_SIGSEGV_RECOVERY
417 user_handler
= handler
;
419 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
428 sigsegv_deinstall_handler (void)
430 #if HAVE_SIGSEGV_RECOVERY
431 user_handler
= (sigsegv_handler_t
)NULL
;
433 #if HAVE_STACK_OVERFLOW_RECOVERY
434 if (!stk_user_handler
)
437 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
443 sigsegv_leave_handler (void)
445 #if HAVE_STACK_OVERFLOW_RECOVERY
447 * Reset the system's knowledge that we are executing on the alternate
448 * stack. If we didn't do that, siglongjmp would be needed instead of
449 * longjmp to leave the signal handler.
451 sigsegv_reset_onstack_flag ();
456 stackoverflow_install_handler (stackoverflow_handler_t handler
,
457 void *extra_stack
, unsigned long extra_stack_size
)
459 #if HAVE_STACK_OVERFLOW_RECOVERY
464 remember_stack_top (&dummy
);
470 stk_user_handler
= handler
;
471 stk_extra_stack
= (unsigned long) extra_stack
;
472 stk_extra_stack_size
= extra_stack_size
;
474 set_signal_stack (extra_stack
, extra_stack_size
);
475 #else /* HAVE_SIGALTSTACK */
478 ss
.ss_sp
= extra_stack
;
479 ss
.ss_size
= extra_stack_size
;
480 ss
.ss_flags
= 0; /* no SS_DISABLE */
481 if (sigaltstack (&ss
, (stack_t
*)0) < 0)
486 /* Install the signal handlers with SA_ONSTACK. */
487 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
495 stackoverflow_deinstall_handler (void)
497 #if HAVE_STACK_OVERFLOW_RECOVERY
498 stk_user_handler
= (stackoverflow_handler_t
) NULL
;
500 #if HAVE_SIGSEGV_RECOVERY
503 /* Reinstall the signal handlers without SA_ONSTACK, to avoid Linux
505 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
510 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
514 /* We cannot undo the effect of set_signal_stack. */
515 fprintf (stderr
, "libsigsegv (stackoverflow_deinstall_handler): not supported on this platform\n");
516 #else /* HAVE_SIGALTSTACK */
519 ss
.ss_flags
= SS_DISABLE
;
520 if (sigaltstack (&ss
, (stack_t
*) 0) < 0)
521 perror ("libsigsegv (stackoverflow_deinstall_handler)");