From e3ea810706b94a625eadc27dda079d74cdd68440 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 25 Aug 2008 06:26:56 -0600 Subject: [PATCH] c-stack: test that stack overflow can be caught * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Also check that platform allows handling stack overflow; at least OS/2 EMX has sigaltstack, but crashes before transferring control to handler on stack overflow. * lib/c-stack.c [HAVE_SIGALTSTACK]: Adjust conditions to also check for HAVE_STACK_OVERFLOW_HANDLING. Reported by Elbert Pol. Signed-off-by: Eric Blake --- ChangeLog | 11 +++++++ lib/c-stack.c | 8 ++++-- m4/c-stack.m4 | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 708cefd28..92dd18516 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-08-25 Eric Blake + + c-stack: test that stack overflow can be caught + * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Also check + that platform allows handling stack overflow; at least OS/2 EMX + has sigaltstack, but crashes before transferring control to + handler on stack overflow. + * lib/c-stack.c [HAVE_SIGALTSTACK]: Adjust conditions to also + check for HAVE_STACK_OVERFLOW_HANDLING. + Reported by Elbert Pol. + 2008-08-25 Bruno Haible * doc/posix-functions/strftime.texi: Fix description of strftime diff --git a/lib/c-stack.c b/lib/c-stack.c index c46c23136..6802665f5 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -117,7 +117,8 @@ die (int signo) abort (); } -#if (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV +#if (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK \ + && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV /* Storage for the alternate signal stack. */ static union @@ -210,7 +211,7 @@ c_stack_action (void (*action) (int)) return 0; } -#elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK +#elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING /* Direction of the C runtime stack. This function is async-signal-safe. */ @@ -316,7 +317,8 @@ c_stack_action (void (*action) (int)) return sigaction (SIGSEGV, &act, NULL); } -#else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV) */ +#else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK + && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV) */ int c_stack_action (void (*action) (int) __attribute__ ((unused))) diff --git a/m4/c-stack.m4 b/m4/c-stack.m4 index 1db2a5065..885b66286 100644 --- a/m4/c-stack.m4 +++ b/m4/c-stack.m4 @@ -7,7 +7,7 @@ # Written by Paul Eggert. -# serial 4 +# serial 5 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], [# for STACK_DIRECTION @@ -16,6 +16,90 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], AC_CHECK_HEADERS_ONCE([ucontext.h]) AC_CACHE_CHECK([for working C stack overflow detection], + [ac_cv_sys_stack_overflow_works], + [AC_TRY_RUN( + [ + #include + #include + #if HAVE_SETRLIMIT + # include + # include + # include + #endif + #ifndef SIGSTKSZ + # define SIGSTKSZ 16384 + #endif + + static union + { + char buffer[SIGSTKSZ]; + long double ld; + long u; + void *p; + } alternate_signal_stack; + + static void + segv_handler (int signo) + { + _exit (0); + } + + static int + c_stack_action () + { + stack_t st; + struct sigaction act; + int r; + + st.ss_flags = 0; + st.ss_sp = alternate_signal_stack.buffer; + st.ss_size = sizeof alternate_signal_stack.buffer; + r = sigaltstack (&st, 0); + if (r != 0) + return r; + + sigemptyset (&act.sa_mask); + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; + act.sa_handler = segv_handler; + return sigaction (SIGSEGV, &act, 0); + } + + static int + recurse (char *p) + { + char array[500]; + array[0] = 1; + return *p + recurse (array); + } + + int + main () + { + #if HAVE_SETRLIMIT && defined RLIMIT_STACK + /* Before starting the endless recursion, try to be friendly + to the user's machine. On some Linux 2.2.x systems, there + is no stack limit for user processes at all. We don't want + to kill such systems. */ + struct rlimit rl; + rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */ + setrlimit (RLIMIT_STACK, &rl); + #endif + + c_stack_action (); + return recurse ("\1"); + } + ], + [ac_cv_sys_stack_overflow_works=yes], + [ac_cv_sys_stack_overflow_works=no], + [ac_cv_sys_stack_overflow_works=cross-compiling])]) + + if test $ac_cv_sys_stack_overflow_works = yes; then + AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1], + [Define to 1 if extending the stack slightly past the limit causes + a SIGSEGV which can be handled on an alternate stack established + with sigaltstack.]) + + AC_CACHE_CHECK([for precise C stack overflow detection], ac_cv_sys_xsi_stack_overflow_heuristic, [AC_TRY_RUN( [ @@ -29,6 +113,9 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], # include # include #endif + #ifndef SIGSTKSZ + # define SIGSTKSZ 16384 + #endif static union { @@ -131,7 +218,8 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], with the X/Open System Interface (XSI) option and is a standardized way to implement a SEGV-based stack overflow detection heuristic.]) - fi]) + fi + fi]) AC_DEFUN([gl_PREREQ_C_STACK], -- 2.11.0