| 1 | # sigaltstack.m4 serial 15
 | 
|---|
| 2 | dnl Copyright (C) 2002-2021 Free Software Foundation, Inc.
 | 
|---|
| 3 | dnl This file is free software, distributed under the terms of the GNU
 | 
|---|
| 4 | dnl General Public License.  As a special exception to the GNU General
 | 
|---|
| 5 | dnl Public License, this file may be distributed as part of a program
 | 
|---|
| 6 | dnl that contains a configuration script generated by Autoconf, under
 | 
|---|
| 7 | dnl the same distribution terms as the rest of that program.
 | 
|---|
| 8 | 
 | 
|---|
| 9 | dnl Written by Bruno Haible and Eric Blake.
 | 
|---|
| 10 | 
 | 
|---|
| 11 | AC_DEFUN([SV_SIGALTSTACK],
 | 
|---|
| 12 | [
 | 
|---|
| 13 |   AC_REQUIRE([AC_PROG_CC])
 | 
|---|
| 14 |   AC_REQUIRE([AC_CANONICAL_HOST])
 | 
|---|
| 15 | 
 | 
|---|
| 16 |   AC_CHECK_FUNCS_ONCE([sigaltstack setrlimit])
 | 
|---|
| 17 | 
 | 
|---|
| 18 |   if test "$ac_cv_func_sigaltstack" = yes; then
 | 
|---|
| 19 |     AC_CHECK_TYPE([stack_t], ,
 | 
|---|
| 20 |       [AC_DEFINE(stack_t, [struct sigaltstack],
 | 
|---|
| 21 |          [Define to 'struct sigaltstack' if that's the type of the argument to sigaltstack])
 | 
|---|
| 22 |       ],
 | 
|---|
| 23 |       [
 | 
|---|
| 24 | #include <signal.h>
 | 
|---|
| 25 | #if HAVE_SYS_SIGNAL_H
 | 
|---|
| 26 | # include <sys/signal.h>
 | 
|---|
| 27 | #endif
 | 
|---|
| 28 |       ])
 | 
|---|
| 29 |   fi
 | 
|---|
| 30 | 
 | 
|---|
| 31 |   AC_CACHE_CHECK([for working sigaltstack], [sv_cv_sigaltstack], [
 | 
|---|
| 32 |     if test "$ac_cv_func_sigaltstack" = yes; then
 | 
|---|
| 33 |       case "$host_os" in
 | 
|---|
| 34 |         macos* | darwin[[6-9]]* | darwin[[1-9]][[0-9]]*)
 | 
|---|
| 35 |           # On MacOS X 10.2 or newer, just assume that if it compiles, it will
 | 
|---|
| 36 |           # work. If we were to perform the real test, 1 Crash Report dialog
 | 
|---|
| 37 |           # window would pop up.
 | 
|---|
| 38 |           AC_LINK_IFELSE([
 | 
|---|
| 39 |             AC_LANG_PROGRAM([[#include <signal.h>]],
 | 
|---|
| 40 |               [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
 | 
|---|
| 41 |             [sv_cv_sigaltstack="guessing yes"],
 | 
|---|
| 42 |             [sv_cv_sigaltstack=no])
 | 
|---|
| 43 |           ;;
 | 
|---|
| 44 |         *)
 | 
|---|
| 45 |           AC_RUN_IFELSE([
 | 
|---|
| 46 |             AC_LANG_SOURCE([[
 | 
|---|
| 47 | #include <stdlib.h>
 | 
|---|
| 48 | #include <signal.h>
 | 
|---|
| 49 | #if HAVE_SYS_SIGNAL_H
 | 
|---|
| 50 | # include <sys/signal.h>
 | 
|---|
| 51 | #endif
 | 
|---|
| 52 | #if HAVE_SETRLIMIT
 | 
|---|
| 53 | # include <sys/types.h>
 | 
|---|
| 54 | # include <sys/time.h>
 | 
|---|
| 55 | # include <sys/resource.h>
 | 
|---|
| 56 | #endif
 | 
|---|
| 57 | void stackoverflow_handler (int sig)
 | 
|---|
| 58 | {
 | 
|---|
| 59 |   /* If we get here, the stack overflow was caught.  */
 | 
|---|
| 60 |   exit (0);
 | 
|---|
| 61 | }
 | 
|---|
| 62 | volatile int * recurse_1 (volatile int n, volatile int *p)
 | 
|---|
| 63 | {
 | 
|---|
| 64 |   if (n >= 0)
 | 
|---|
| 65 |     *recurse_1 (n + 1, p) += n;
 | 
|---|
| 66 |   return p;
 | 
|---|
| 67 | }
 | 
|---|
| 68 | int recurse (volatile int n)
 | 
|---|
| 69 | {
 | 
|---|
| 70 |   int sum = 0;
 | 
|---|
| 71 |   return *recurse_1 (n, &sum);
 | 
|---|
| 72 | }
 | 
|---|
| 73 | char mystack[2 * (1 << 24)];
 | 
|---|
| 74 | int main ()
 | 
|---|
| 75 | {
 | 
|---|
| 76 |   stack_t altstack;
 | 
|---|
| 77 |   struct sigaction action;
 | 
|---|
| 78 | #if defined HAVE_SETRLIMIT && defined RLIMIT_STACK
 | 
|---|
| 79 |   /* Before starting the endless recursion, try to be friendly to the user's
 | 
|---|
| 80 |      machine.  On some Linux 2.2.x systems, there is no stack limit for user
 | 
|---|
| 81 |      processes at all.  We don't want to kill such systems.  */
 | 
|---|
| 82 |   struct rlimit rl;
 | 
|---|
| 83 |   rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
 | 
|---|
| 84 |   setrlimit (RLIMIT_STACK, &rl);
 | 
|---|
| 85 | #endif
 | 
|---|
| 86 |   /* Install the alternate stack.  Use the midpoint of mystack, to guard
 | 
|---|
| 87 |      against a buggy interpretation of ss_sp on IRIX.  */
 | 
|---|
| 88 | #ifdef SIGSTKSZ
 | 
|---|
| 89 |   if (sizeof mystack / 2 < SIGSTKSZ)
 | 
|---|
| 90 |     exit (3);
 | 
|---|
| 91 | #endif
 | 
|---|
| 92 |   altstack.ss_sp = mystack + sizeof mystack / 2;
 | 
|---|
| 93 |   altstack.ss_size = sizeof mystack / 2;
 | 
|---|
| 94 |   altstack.ss_flags = 0; /* no SS_DISABLE */
 | 
|---|
| 95 |   if (sigaltstack (&altstack, NULL) < 0)
 | 
|---|
| 96 |     exit (1);
 | 
|---|
| 97 |   /* Install the SIGSEGV handler.  */
 | 
|---|
| 98 |   sigemptyset (&action.sa_mask);
 | 
|---|
| 99 |   action.sa_handler = &stackoverflow_handler;
 | 
|---|
| 100 |   action.sa_flags = SA_ONSTACK;
 | 
|---|
| 101 |   sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
 | 
|---|
| 102 |   sigaction (SIGBUS, &action, (struct sigaction *) NULL);
 | 
|---|
| 103 |   /* Provoke a stack overflow.  */
 | 
|---|
| 104 |   recurse (0);
 | 
|---|
| 105 |   exit (2);
 | 
|---|
| 106 | }]])],
 | 
|---|
| 107 |             [sv_cv_sigaltstack=yes],
 | 
|---|
| 108 |             [sv_cv_sigaltstack=no],
 | 
|---|
| 109 |             [
 | 
|---|
| 110 |               dnl FIXME: Put in some more known values here.
 | 
|---|
| 111 |               case "$host_os" in
 | 
|---|
| 112 |                 *)
 | 
|---|
| 113 |                   AC_LINK_IFELSE([
 | 
|---|
| 114 |                     AC_LANG_PROGRAM([[#include <signal.h>]],
 | 
|---|
| 115 |                       [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
 | 
|---|
| 116 |                     [sv_cv_sigaltstack="guessing yes"],
 | 
|---|
| 117 |                     [sv_cv_sigaltstack=no])
 | 
|---|
| 118 |                   ;;
 | 
|---|
| 119 |               esac
 | 
|---|
| 120 |             ])
 | 
|---|
| 121 |           ;;
 | 
|---|
| 122 |       esac
 | 
|---|
| 123 |     else
 | 
|---|
| 124 |       sv_cv_sigaltstack=no
 | 
|---|
| 125 |     fi
 | 
|---|
| 126 |   ])
 | 
|---|
| 127 |   if test "$sv_cv_sigaltstack" != no; then
 | 
|---|
| 128 |     AC_DEFINE([HAVE_WORKING_SIGALTSTACK], [1],
 | 
|---|
| 129 |       [Define if you have the sigaltstack() function and it works.])
 | 
|---|
| 130 | 
 | 
|---|
| 131 |     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
 | 
|---|
| 132 |     dnl of the memory block designated as an alternate stack. But IRIX 5.3
 | 
|---|
| 133 |     dnl interprets it as the highest address!
 | 
|---|
| 134 |     AC_CACHE_CHECK([for correct stack_t interpretation],
 | 
|---|
| 135 |       [sv_cv_sigaltstack_low_base], [
 | 
|---|
| 136 |       AC_RUN_IFELSE([
 | 
|---|
| 137 |         AC_LANG_SOURCE([[
 | 
|---|
| 138 | #include <stdlib.h>
 | 
|---|
| 139 | #include <signal.h>
 | 
|---|
| 140 | #if HAVE_SYS_SIGNAL_H
 | 
|---|
| 141 | # include <sys/signal.h>
 | 
|---|
| 142 | #endif
 | 
|---|
| 143 | volatile char *stack_lower_bound;
 | 
|---|
| 144 | volatile char *stack_upper_bound;
 | 
|---|
| 145 | static void check_stack_location (volatile char *addr)
 | 
|---|
| 146 | {
 | 
|---|
| 147 |   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
 | 
|---|
| 148 |     exit (0);
 | 
|---|
| 149 |   else
 | 
|---|
| 150 |     exit (1);
 | 
|---|
| 151 | }
 | 
|---|
| 152 | static void stackoverflow_handler (int sig)
 | 
|---|
| 153 | {
 | 
|---|
| 154 |   char dummy;
 | 
|---|
| 155 |   check_stack_location (&dummy);
 | 
|---|
| 156 | }
 | 
|---|
| 157 | char mystack[2 * (1 << 24)];
 | 
|---|
| 158 | int main ()
 | 
|---|
| 159 | {
 | 
|---|
| 160 |   stack_t altstack;
 | 
|---|
| 161 |   struct sigaction action;
 | 
|---|
| 162 |   /* Install the alternate stack.  */
 | 
|---|
| 163 |   altstack.ss_sp = mystack + sizeof mystack / 2;
 | 
|---|
| 164 |   altstack.ss_size = sizeof mystack / 2;
 | 
|---|
| 165 |   stack_lower_bound = (char *) altstack.ss_sp;
 | 
|---|
| 166 |   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
 | 
|---|
| 167 |   altstack.ss_flags = 0; /* no SS_DISABLE */
 | 
|---|
| 168 |   if (sigaltstack (&altstack, NULL) < 0)
 | 
|---|
| 169 |     exit (2);
 | 
|---|
| 170 |   /* Install the SIGSEGV handler.  */
 | 
|---|
| 171 |   sigemptyset (&action.sa_mask);
 | 
|---|
| 172 |   action.sa_handler = &stackoverflow_handler;
 | 
|---|
| 173 |   action.sa_flags = SA_ONSTACK;
 | 
|---|
| 174 |   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
 | 
|---|
| 175 |     exit(3);
 | 
|---|
| 176 |   /* Provoke a SIGSEGV.  */
 | 
|---|
| 177 |   raise (SIGSEGV);
 | 
|---|
| 178 |   exit (3);
 | 
|---|
| 179 | }]])],
 | 
|---|
| 180 |       [sv_cv_sigaltstack_low_base=yes],
 | 
|---|
| 181 |       [sv_cv_sigaltstack_low_base=no],
 | 
|---|
| 182 |       [
 | 
|---|
| 183 |         dnl FIXME: Put in some more known values here.
 | 
|---|
| 184 |         case "$host_os" in
 | 
|---|
| 185 |           irix5*) sv_cv_sigaltstack_low_base="no" ;;
 | 
|---|
| 186 |           *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
 | 
|---|
| 187 |         esac
 | 
|---|
| 188 |       ])
 | 
|---|
| 189 |     ])
 | 
|---|
| 190 |     if test "$sv_cv_sigaltstack_low_base" = no; then
 | 
|---|
| 191 |       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
 | 
|---|
| 192 |         [Define if sigaltstack() interprets the stack_t.ss_sp field incorrectly,
 | 
|---|
| 193 |          as the highest address of the alternate stack range rather than as the
 | 
|---|
| 194 |          lowest address.])
 | 
|---|
| 195 |     fi
 | 
|---|
| 196 |   fi
 | 
|---|
| 197 | ])
 | 
|---|