1*75f6d617Schristos# Check prerequisites for compiling lib/c-stack.c. 2*75f6d617Schristos 3*75f6d617Schristos# Copyright (C) 2002 Free Software Foundation, Inc. 4*75f6d617Schristos 5*75f6d617Schristos# This program is free software; you can redistribute it and/or modify 6*75f6d617Schristos# it under the terms of the GNU General Public License as published by 7*75f6d617Schristos# the Free Software Foundation; either version 2, or (at your option) 8*75f6d617Schristos# any later version. 9*75f6d617Schristos 10*75f6d617Schristos# This program is distributed in the hope that it will be useful, 11*75f6d617Schristos# but WITHOUT ANY WARRANTY; without even the implied warranty of 12*75f6d617Schristos# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*75f6d617Schristos# GNU General Public License for more details. 14*75f6d617Schristos 15*75f6d617Schristos# You should have received a copy of the GNU General Public License 16*75f6d617Schristos# along with this program; if not, write to the Free Software 17*75f6d617Schristos# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18*75f6d617Schristos# 02111-1307, USA. 19*75f6d617Schristos 20*75f6d617SchristosAC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], 21*75f6d617Schristos [# for STACK_DIRECTION 22*75f6d617Schristos AC_REQUIRE([AC_FUNC_ALLOCA]) 23*75f6d617Schristos 24*75f6d617Schristos AC_CACHE_CHECK([for working C stack overflow detection], 25*75f6d617Schristos ac_cv_sys_xsi_stack_overflow_heuristic, 26*75f6d617Schristos [AC_TRY_RUN( 27*75f6d617Schristos [ 28*75f6d617Schristos #include <signal.h> 29*75f6d617Schristos #include <ucontext.h> 30*75f6d617Schristos 31*75f6d617Schristos static union 32*75f6d617Schristos { 33*75f6d617Schristos char buffer[SIGSTKSZ]; 34*75f6d617Schristos long double ld; 35*75f6d617Schristos uintmax_t u; 36*75f6d617Schristos void *p; 37*75f6d617Schristos } alternate_signal_stack; 38*75f6d617Schristos 39*75f6d617Schristos #if STACK_DIRECTION 40*75f6d617Schristos # define find_stack_direction(ptr) STACK_DIRECTION 41*75f6d617Schristos #else 42*75f6d617Schristos static int 43*75f6d617Schristos find_stack_direction (char const *addr) 44*75f6d617Schristos { 45*75f6d617Schristos char dummy; 46*75f6d617Schristos return (! addr ? find_stack_direction (&dummy) 47*75f6d617Schristos : addr < &dummy ? 1 : -1); 48*75f6d617Schristos } 49*75f6d617Schristos #endif 50*75f6d617Schristos 51*75f6d617Schristos static void 52*75f6d617Schristos segv_handler (int signo, siginfo_t *info, void *context) 53*75f6d617Schristos { 54*75f6d617Schristos if (0 < info->si_code) 55*75f6d617Schristos { 56*75f6d617Schristos ucontext_t const *user_context = context; 57*75f6d617Schristos char const *stack_min = user_context->uc_stack.ss_sp; 58*75f6d617Schristos size_t stack_size = user_context->uc_stack.ss_size; 59*75f6d617Schristos char const *faulting_address = info->si_addr; 60*75f6d617Schristos size_t s = faulting_address - stack_min; 61*75f6d617Schristos size_t page_size = sysconf (_SC_PAGESIZE); 62*75f6d617Schristos if (find_stack_direction (0) < 0) 63*75f6d617Schristos s += page_size; 64*75f6d617Schristos if (s < stack_size + page_size) 65*75f6d617Schristos _exit (0); 66*75f6d617Schristos } 67*75f6d617Schristos 68*75f6d617Schristos _exit (1); 69*75f6d617Schristos } 70*75f6d617Schristos 71*75f6d617Schristos static int 72*75f6d617Schristos c_stack_action (void) 73*75f6d617Schristos { 74*75f6d617Schristos stack_t st; 75*75f6d617Schristos struct sigaction act; 76*75f6d617Schristos int r; 77*75f6d617Schristos 78*75f6d617Schristos st.ss_flags = 0; 79*75f6d617Schristos st.ss_sp = alternate_signal_stack.buffer; 80*75f6d617Schristos st.ss_size = sizeof alternate_signal_stack.buffer; 81*75f6d617Schristos r = sigaltstack (&st, 0); 82*75f6d617Schristos if (r != 0) 83*75f6d617Schristos return r; 84*75f6d617Schristos 85*75f6d617Schristos sigemptyset (&act.sa_mask); 86*75f6d617Schristos act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; 87*75f6d617Schristos act.sa_sigaction = segv_handler; 88*75f6d617Schristos return sigaction (SIGSEGV, &act, 0); 89*75f6d617Schristos } 90*75f6d617Schristos 91*75f6d617Schristos static int 92*75f6d617Schristos recurse (char *p) 93*75f6d617Schristos { 94*75f6d617Schristos char array[500]; 95*75f6d617Schristos array[0] = 1; 96*75f6d617Schristos return *p + recurse (array); 97*75f6d617Schristos } 98*75f6d617Schristos 99*75f6d617Schristos int 100*75f6d617Schristos main (void) 101*75f6d617Schristos { 102*75f6d617Schristos c_stack_action (); 103*75f6d617Schristos return recurse ("\1"); 104*75f6d617Schristos } 105*75f6d617Schristos ], 106*75f6d617Schristos [ac_cv_sys_xsi_stack_overflow_heuristic=yes], 107*75f6d617Schristos [ac_cv_sys_xsi_stack_overflow_heuristic=no], 108*75f6d617Schristos [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])]) 109*75f6d617Schristos 110*75f6d617Schristos if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then 111*75f6d617Schristos AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1, 112*75f6d617Schristos [Define to 1 if extending the stack slightly past the limit causes 113*75f6d617Schristos a SIGSEGV, and an alternate stack can be established with sigaltstack, 114*75f6d617Schristos and the signal handler is passed a context that specifies the 115*75f6d617Schristos run time stack. This behavior is defined by POSIX 1003.1-2001 116*75f6d617Schristos with the X/Open System Interface (XSI) option 117*75f6d617Schristos and is a standardized way to implement a SEGV-based stack 118*75f6d617Schristos overflow detection heuristic.]) 119*75f6d617Schristos fi]) 120*75f6d617Schristos 121*75f6d617Schristos 122*75f6d617SchristosAC_DEFUN([jm_PREREQ_C_STACK], 123*75f6d617Schristos [AC_REQUIRE([jm_AC_TYPE_UINTMAX_T]) 124*75f6d617Schristos AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC]) 125*75f6d617Schristos 126*75f6d617Schristos # for STACK_DIRECTION 127*75f6d617Schristos AC_REQUIRE([AC_FUNC_ALLOCA]) 128*75f6d617Schristos 129*75f6d617Schristos AC_CHECK_HEADERS(unistd.h) 130*75f6d617Schristos 131*75f6d617Schristos AC_CHECK_TYPES([siginfo_t, stack_t], , , [#include <signal.h>])]) 132