1 /* Fault handler information. Unix version.
2 Copyright (C) 1993-1999, 2002-2003, 2006, 2008-2009 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. */
18 /* Persuade glibc <sys/ucontext.h> to declare macros designating register
19 indices: REG_RSP on x86_64, REG_ESP on i386. */
24 /* On the average Unix platform, we define
27 if there is a fault-*.h include file which defines
28 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
30 HAVE_STACK_OVERFLOW_RECOVERY
31 if HAVE_SIGALTSTACK is set and
32 at least two of the following are true:
33 A) There is a fault-*.h include file which defines
34 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
35 B) There is a fault-*.h include file which defines
36 SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_STACKPOINTER.
37 C) There is a stackvma-*.c, other than stackvma-none.c, which
38 defines sigsegv_get_vma.
40 Why? Obviously, to catch stack overflow, we need an alternate signal
41 stack; this requires kernel support. But we also need to distinguish
42 (with a reasonable confidence) a stack overflow from a regular SIGSEGV.
43 If we have A) and B), we use the
44 Heuristic AB: If the fault address is near the stack pointer, it's a
46 If we have A) and C), we use the
47 Heuristic AC: If the fault address is near and beyond the bottom of
48 the stack's virtual memory area, it's a stack overflow.
49 If we have B) and C), we use the
50 Heuristic BC: If the stack pointer is near the bottom of the stack's
51 virtual memory area, it's a stack overflow.
52 This heuristic comes in two flavours: On OSes which let the stack's
53 VMA grow continuously, we determine the bottom by use of getrlimit().
54 On OSes which preallocate the stack's VMA with its maximum size
55 (like BeOS), we use the stack's VMA directly.
58 #include <stddef.h> /* needed for NULL on SunOS4 */
62 # include <sys/signal.h>
68 #define SS_DISABLE SA_DISABLE
74 #if HAVE_STACK_OVERFLOW_RECOVERY
76 #include <stdio.h> /* perror */
79 # include <sys/types.h>
80 # include <sys/time.h>
81 # include <sys/resource.h> /* declares struct rlimit */
84 /* Platform dependent:
85 Determine the virtual memory area of a given address. */
88 /* Platform dependent:
89 Leaving a signal handler executing on the alternate stack. */
94 /* Address of the last byte belonging to the stack vma. */
95 static unsigned long stack_top
= 0;
97 /* Needs to be called once only. */
99 remember_stack_top (void *some_variable_on_stack
)
101 struct vma_struct vma
;
103 if (sigsegv_get_vma ((unsigned long) some_variable_on_stack
, &vma
) >= 0)
104 stack_top
= vma
.end
- 1;
107 #endif /* HAVE_STACKVMA */
109 static stackoverflow_handler_t stk_user_handler
= (stackoverflow_handler_t
)NULL
;
110 static unsigned long stk_extra_stack
;
111 static unsigned long stk_extra_stack_size
;
113 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
115 #if HAVE_SIGSEGV_RECOVERY
117 /* User's SIGSEGV handler. */
118 static sigsegv_handler_t user_handler
= (sigsegv_handler_t
)NULL
;
120 #endif /* HAVE_SIGSEGV_RECOVERY */
123 /* Our SIGSEGV handler, with OS dependent argument list. */
125 #if HAVE_SIGSEGV_RECOVERY
128 sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST
)
130 void *address
= (void *) (SIGSEGV_FAULT_ADDRESS
);
132 #if HAVE_STACK_OVERFLOW_RECOVERY
133 #if !(HAVE_STACKVMA || defined SIGSEGV_FAULT_STACKPOINTER)
134 #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!"
137 /* Call user's handler. */
138 if (user_handler
&& (*user_handler
) (address
, 0))
140 /* Handler successful. */
144 /* Handler declined responsibility. */
146 /* Did the user install a stack overflow handler? */
147 if (stk_user_handler
)
149 /* See whether it was a stack overflow. If so, longjump away. */
150 #ifdef SIGSEGV_FAULT_STACKPOINTER
151 unsigned long old_sp
= (unsigned long) (SIGSEGV_FAULT_STACKPOINTER
);
153 unsigned long old_bsp
= (unsigned long) (SIGSEGV_FAULT_BSP_POINTER
);
158 /* Were we able to determine the stack top? */
161 /* Determine stack bounds. */
163 struct vma_struct vma
;
167 ret
= sigsegv_get_vma (stack_top
, &vma
);
171 /* Heuristic AC: If the fault_address is nearer to the stack
172 segment's [start,end] than to the previous segment, we
173 consider it a stack overflow.
174 In the case of IA-64, we know that the previous segment
175 is the up-growing bsp segment, and either of the two
176 stacks can overflow. */
177 unsigned long addr
= (unsigned long) address
;
180 if (addr
>= vma
.prev_end
&& addr
<= vma
.end
- 1)
182 #if STACK_DIRECTION < 0
183 if (addr
>= vma
.start
184 ? (addr
<= vma
.end
- 1)
185 : vma
.is_near_this (addr
, &vma
))
187 if (addr
<= vma
.end
- 1
188 ? (addr
>= vma
.start
)
189 : vma
.is_near_this (addr
, &vma
))
193 /* Heuristic AB: If the fault address is near the stack pointer,
194 it's a stack overflow. */
195 unsigned long addr
= (unsigned long) address
;
197 if ((addr
<= old_sp
+ 4096 && old_sp
<= addr
+ 4096)
199 || (addr
<= old_bsp
+ 4096 && old_bsp
<= addr
+ 4096)
206 #ifdef SIGSEGV_FAULT_STACKPOINTER
208 (old_sp
>= stk_extra_stack
209 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
);
210 stackoverflow_context_t context
= (SIGSEGV_FAULT_CONTEXT
);
213 stackoverflow_context_t context
= (void *) 0;
215 /* Call user's handler. */
216 (*stk_user_handler
) (emergency
, context
);
221 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
223 if (user_handler
&& (*user_handler
) (address
, 1))
225 /* Handler successful. */
229 /* Handler declined responsibility for real. */
231 /* Remove ourselves and dump core. */
232 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
235 #if HAVE_STACK_OVERFLOW_RECOVERY
237 #endif /* HAVE_STACK_OVERFLOW_RECOVERY */
240 #elif HAVE_STACK_OVERFLOW_RECOVERY
243 #ifdef SIGSEGV_FAULT_STACKPOINTER
244 sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST
)
246 sigsegv_handler (int sig
)
249 #if !((HAVE_GETRLIMIT && defined RLIMIT_STACK) || defined SIGSEGV_FAULT_STACKPOINTER)
250 #error "Insufficient heuristics for detecting a stack overflow. Either define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
253 /* Did the user install a handler? */
254 if (stk_user_handler
)
256 /* See whether it was a stack overflow. If so, longjump away. */
257 #ifdef SIGSEGV_FAULT_STACKPOINTER
258 unsigned long old_sp
= (unsigned long) (SIGSEGV_FAULT_STACKPOINTER
);
261 /* Were we able to determine the stack top? */
264 /* Determine stack bounds. */
266 struct vma_struct vma
;
269 if (sigsegv_get_vma (stack_top
, &vma
) >= 0)
271 #if HAVE_GETRLIMIT && defined RLIMIT_STACK
272 /* Heuristic BC: If the stack size has reached its maximal size,
273 and old_sp is near the low end, we consider it a stack
277 if (getrlimit (RLIMIT_STACK
, &rl
) >= 0)
279 unsigned long current_stack_size
= vma
.end
- vma
.start
;
280 unsigned long max_stack_size
= rl
.rlim_cur
;
281 if (current_stack_size
<= max_stack_size
+ 4096
282 && max_stack_size
<= current_stack_size
+ 4096
287 #ifdef SIGSEGV_FAULT_STACKPOINTER
288 /* Heuristic BC: If we know old_sp, and it is neither
289 near the low end, nor in the alternate stack, then
290 it's probably not a stack overflow. */
291 && ((old_sp
>= stk_extra_stack
292 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
)
293 #if STACK_DIRECTION < 0
294 || (old_sp
<= vma
.start
+ 4096
295 && vma
.start
<= old_sp
+ 4096))
297 || (old_sp
<= vma
.end
+ 4096
298 && vma
.end
<= old_sp
+ 4096))
303 #ifdef SIGSEGV_FAULT_STACKPOINTER
305 (old_sp
>= stk_extra_stack
306 && old_sp
<= stk_extra_stack
+ stk_extra_stack_size
);
307 stackoverflow_context_t context
= (SIGSEGV_FAULT_CONTEXT
);
310 stackoverflow_context_t context
= (void *) 0;
312 /* Call user's handler. */
313 (*stk_user_handler
)(emergency
,context
);
321 /* Remove ourselves and dump core. */
322 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
329 install_for (int sig
)
331 struct sigaction action
;
333 #ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
334 action
.sa_sigaction
= &sigsegv_handler
;
336 action
.sa_handler
= (void (*) (int)) &sigsegv_handler
;
338 /* Block most signals while SIGSEGV is being handled. */
339 /* Signals SIGKILL, SIGSTOP cannot be blocked. */
340 /* Signals SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU are not blocked because
341 dealing with these signals seems dangerous. */
342 /* Signals SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTRAP, SIGIOT, SIGEMT, SIGBUS,
343 SIGSYS, SIGSTKFLT are not blocked because these are synchronous signals,
344 which may require immediate intervention, otherwise the process may
346 sigemptyset (&action
.sa_mask
);
348 sigaddset (&action
.sa_mask
,SIGHUP
);
351 sigaddset (&action
.sa_mask
,SIGINT
);
354 sigaddset (&action
.sa_mask
,SIGQUIT
);
357 sigaddset (&action
.sa_mask
,SIGPIPE
);
360 sigaddset (&action
.sa_mask
,SIGALRM
);
363 sigaddset (&action
.sa_mask
,SIGTERM
);
366 sigaddset (&action
.sa_mask
,SIGUSR1
);
369 sigaddset (&action
.sa_mask
,SIGUSR2
);
372 sigaddset (&action
.sa_mask
,SIGCHLD
);
375 sigaddset (&action
.sa_mask
,SIGCLD
);
378 sigaddset (&action
.sa_mask
,SIGURG
);
381 sigaddset (&action
.sa_mask
,SIGIO
);
384 sigaddset (&action
.sa_mask
,SIGPOLL
);
387 sigaddset (&action
.sa_mask
,SIGXCPU
);
390 sigaddset (&action
.sa_mask
,SIGXFSZ
);
393 sigaddset (&action
.sa_mask
,SIGVTALRM
);
396 sigaddset (&action
.sa_mask
,SIGPROF
);
399 sigaddset (&action
.sa_mask
,SIGPWR
);
402 sigaddset (&action
.sa_mask
,SIGLOST
);
405 sigaddset (&action
.sa_mask
,SIGWINCH
);
407 /* Note that sigaction() implicitly adds sig itself to action.sa_mask. */
408 /* Ask the OS to provide a structure siginfo_t to the handler. */
409 #ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
410 action
.sa_flags
= SA_SIGINFO
;
414 #if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGALTSTACK /* not BeOS */
415 /* Work around Linux 2.2.5 bug: If SA_ONSTACK is specified but sigaltstack()
416 has not been called, the kernel will busy loop, eating CPU time. So
417 avoid setting SA_ONSTACK until the user has requested stack overflow
419 if (stk_user_handler
)
420 action
.sa_flags
|= SA_ONSTACK
;
422 sigaction (sig
, &action
, (struct sigaction
*) NULL
);
426 sigsegv_install_handler (sigsegv_handler_t handler
)
428 #if HAVE_SIGSEGV_RECOVERY
429 user_handler
= handler
;
431 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
440 sigsegv_deinstall_handler (void)
442 #if HAVE_SIGSEGV_RECOVERY
443 user_handler
= (sigsegv_handler_t
)NULL
;
445 #if HAVE_STACK_OVERFLOW_RECOVERY
446 if (!stk_user_handler
)
449 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
455 sigsegv_leave_handler (void (*continuation
) (void*, void*, void*),
456 void* cont_arg1
, void* cont_arg2
, void* cont_arg3
)
458 #if HAVE_STACK_OVERFLOW_RECOVERY
460 * Reset the system's knowledge that we are executing on the alternate
461 * stack. If we didn't do that, siglongjmp would be needed instead of
462 * longjmp to leave the signal handler.
464 sigsegv_reset_onstack_flag ();
466 (*continuation
) (cont_arg1
, cont_arg2
, cont_arg3
);
470 #if !MIXING_UNIX_SIGSEGV_AND_WIN32_STACKOVERFLOW_HANDLING
473 stackoverflow_install_handler (stackoverflow_handler_t handler
,
474 void *extra_stack
, unsigned long extra_stack_size
)
476 #if HAVE_STACK_OVERFLOW_RECOVERY
481 remember_stack_top (&dummy
);
487 stk_user_handler
= handler
;
488 stk_extra_stack
= (unsigned long) extra_stack
;
489 stk_extra_stack_size
= extra_stack_size
;
491 set_signal_stack (extra_stack
, extra_stack_size
);
492 #else /* HAVE_SIGALTSTACK */
495 #if SIGALTSTACK_SS_REVERSED
496 ss
.ss_sp
= (char *) extra_stack
+ extra_stack_size
- sizeof (void *);
497 ss
.ss_size
= extra_stack_size
- sizeof (void *);
499 ss
.ss_sp
= extra_stack
;
500 ss
.ss_size
= extra_stack_size
;
502 ss
.ss_flags
= 0; /* no SS_DISABLE */
503 if (sigaltstack (&ss
, (stack_t
*)0) < 0)
508 /* Install the signal handlers with SA_ONSTACK. */
509 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
517 stackoverflow_deinstall_handler (void)
519 #if HAVE_STACK_OVERFLOW_RECOVERY
520 stk_user_handler
= (stackoverflow_handler_t
) NULL
;
522 #if HAVE_SIGSEGV_RECOVERY
525 /* Reinstall the signal handlers without SA_ONSTACK, to avoid Linux
527 SIGSEGV_FOR_ALL_SIGNALS (sig
, install_for (sig
);)
532 SIGSEGV_FOR_ALL_SIGNALS (sig
, signal (sig
, SIG_DFL
);)
536 /* We cannot undo the effect of set_signal_stack. */
537 fprintf (stderr
, "libsigsegv (stackoverflow_deinstall_handler): not supported on this platform\n");
538 #else /* HAVE_SIGALTSTACK */
541 ss
.ss_flags
= SS_DISABLE
;
542 if (sigaltstack (&ss
, (stack_t
*) 0) < 0)
543 perror ("libsigsegv (stackoverflow_deinstall_handler)");
550 #endif /* !MIXING_UNIX_SIGSEGV_AND_WIN32_STACKOVERFLOW_HANDLING */