bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: c-stack and Irix - libsigsegv


From: Bruno Haible
Subject: Re: c-stack and Irix - libsigsegv
Date: Sun, 21 Sep 2008 16:03:54 +0200
User-agent: KMail/1.5.4

Hi Eric,

> Here's the minimal patch needed to CVS libsigsegv to expose the bug, as
> well as work around it for Irix 5.3.

Nice work! I'm applying this only slightly modified version.
  - In the configuration test, keep room to both sides of the ss_sp value.
    On IRIX, we don't want the test to crash. We want it to exit(1) reasonably.
  - When setting the stack_t in a reversed way, since we don't know exactly
    how the fields are interpreted, don't pass an odd address and reduce the
    size a bit. (Hope that still works!)

I've put up a new tarball
at http://www.haible.de/bruno/gnu/libsigsegv-2.7-pre1.tar.gz


2008-09-21  Eric Blake  <address@hidden>
            Bruno Haible  <address@hidden>

        Detect and work around bug in Irix 5.3 sigaltstack.
        * m4/sigaltstack.m4 (SV_SIGALTSTACK): Test for broken stack_t direction
        in sigaltstack.
        * src/handler-unix.c (stackoverflow_install_handler): Adjust stack
        accordingly.
        * tests/stackoverflow1.c (stack_lower_bound, stack_upper_bound): New
        variables.
        (stackoverflow_handler): Use them to expose IRIX bug.
        (main): Initialize them.

*** NEWS        24 Aug 2008 22:24:52 -0000      1.21
--- NEWS        21 Sep 2008 13:36:42 -0000
***************
*** 1,3 ****
--- 1,7 ----
+ New in 2.7:
+ 
+ * Support for IRIX 5.3. Contributed by Eric Blake.
+ 
  New in 2.6:
  
  * sigsegv_leave_handler is changed. Previously it was a normal function with
*** README      24 Aug 2008 13:54:32 -0000      1.7
--- README      21 Sep 2008 13:36:42 -0000
***************
*** 106,111 ****
--- 106,112 ----
  
  Copyright 1998-1999, 2002-2008  Bruno Haible <address@hidden>
  Copyright 2002-2005  Paolo Bonzini <address@hidden>
+ Copyright 2008  Eric Blake <address@hidden>
  
  This is free software distributed under the GNU General Public Licence
  described in the file COPYING. There is ABSOLUTELY NO WARRANTY, explicit or
*** m4/sigaltstack.m4   24 Aug 2008 20:55:08 -0000      1.11
--- m4/sigaltstack.m4   21 Sep 2008 13:36:42 -0000
***************
*** 1,5 ****
! # sigaltstack.m4 serial 8 (libsigsegv-2.6)
  dnl Copyright (C) 2002-2006, 2008 Bruno Haible <address@hidden>
  dnl This file is free software, distributed under the terms of the GNU
  dnl General Public License.  As a special exception to the GNU General
  dnl Public License, this file may be distributed as part of a program
--- 1,6 ----
! # sigaltstack.m4 serial 9 (libsigsegv-2.7)
  dnl Copyright (C) 2002-2006, 2008 Bruno Haible <address@hidden>
+ dnl Copyright (C) 2008 Eric Blake <address@hidden>
  dnl This file is free software, distributed under the terms of the GNU
  dnl General Public License.  As a special exception to the GNU General
  dnl Public License, this file may be distributed as part of a program
***************
*** 123,127 ****
--- 124,197 ----
    if test "$sv_cv_sigaltstack" != no; then
      AC_DEFINE(HAVE_WORKING_SIGALTSTACK, 1,
        [Define if you have the sigaltstack() function and it works.])
+ 
+     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest 
address
+     dnl of the memory block designated as an alternate stack. But IRIX 5.3
+     dnl interprets it as the highest address!
+     AC_CACHE_CHECK([for correct stack_t interpretation],
+       [sv_cv_sigaltstack_low_base], [
+       AC_RUN_IFELSE([
+         AC_LANG_SOURCE([[
+ #include <stdlib.h>
+ #include <signal.h>
+ #if HAVE_SYS_SIGNAL_H
+ # include <sys/signal.h>
+ #endif
+ #ifndef SIGSTKSZ
+ # define SIGSTKSZ 16384
+ #endif
+ volatile char *stack_lower_bound;
+ volatile char *stack_upper_bound;
+ static void check_stack_location (volatile char *addr)
+ {
+   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
+     exit (0);
+   else
+     exit (1);
+ }
+ static void stackoverflow_handler (int sig)
+ {
+   char dummy;
+   check_stack_location (&dummy);
+ }
+ int main ()
+ {
+   char mystack[2 * SIGSTKSZ];
+   stack_t altstack;
+   struct sigaction action;
+   /* Install the alternate stack.  */
+   altstack.ss_sp = mystack + SIGSTKSZ;
+   altstack.ss_size = SIGSTKSZ;
+   stack_lower_bound = (char *) altstack.ss_sp;
+   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
+   altstack.ss_flags = 0; /* no SS_DISABLE */
+   if (sigaltstack (&altstack, NULL) < 0)
+     exit (2);
+   /* Install the SIGSEGV handler.  */
+   sigemptyset (&action.sa_mask);
+   action.sa_handler = &stackoverflow_handler;
+   action.sa_flags = SA_ONSTACK;
+   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
+     exit(3);
+   /* Provoke a SIGSEGV.  */
+   raise (SIGSEGV);
+   exit (3);
+ }]])],
+       [sv_cv_sigaltstack_low_base=yes],
+       [sv_cv_sigaltstack_low_base=no],
+       [
+         dnl FIXME: Put in some more known values here.
+         case "$host_os" in
+           irix5*) sv_cv_sigaltstack_low_base="no" ;;
+           *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
+         esac
+       ])
+     ])
+     if test "$sv_cv_sigaltstack_low_base" = no; then
+       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
+         [Define if sigaltstack() interprets the stack_t.ss_sp field 
incorrectly,
+          as the highest address of the alternate stack range rather than as 
the
+          lowest address.])
+     fi
    fi
  ])
*** src/handler-unix.c  24 Aug 2008 13:54:16 -0000      1.8
--- src/handler-unix.c  21 Sep 2008 13:36:42 -0000
***************
*** 486,493 ****
--- 486,498 ----
  #else /* HAVE_SIGALTSTACK */
    {
      stack_t ss;
+ #if SIGALTSTACK_SS_REVERSED
+     ss.ss_sp = extra_stack + extra_stack_size - sizeof (void *);
+     ss.ss_size = extra_stack_size - sizeof (void *);
+ #else
      ss.ss_sp = extra_stack;
      ss.ss_size = extra_stack_size;
+ #endif
      ss.ss_flags = 0; /* no SS_DISABLE */
      if (sigaltstack (&ss, (stack_t*)0) < 0)
        return -1;
*** tests/stackoverflow1.c      24 Aug 2008 20:55:17 -0000      1.10
--- tests/stackoverflow1.c      21 Sep 2008 13:36:42 -0000
***************
*** 50,55 ****
--- 50,58 ----
  
  volatile int pass = 0;
  
+ volatile char *stack_lower_bound;
+ volatile char *stack_upper_bound;
+ 
  static void
  stackoverflow_handler_continuation (void *arg1, void *arg2, void *arg3)
  {
***************
*** 60,65 ****
--- 63,72 ----
  void
  stackoverflow_handler (int emergency, stackoverflow_context_t scp)
  {
+   char dummy;
+   volatile char *addr = &dummy;
+   if (!(addr >= stack_lower_bound && addr <= stack_upper_bound))
+     abort ();
    pass++;
    printf ("Stack overflow %d caught.\n", pass);
    sigprocmask (SIG_SETMASK, &mainsigset, NULL);
***************
*** 103,108 ****
--- 110,117 ----
                                       mystack, sizeof (mystack))
        < 0)
      exit (2);
+   stack_lower_bound = mystack;
+   stack_upper_bound = mystack + sizeof (mystack) - 1;
  
    /* Save the current signal mask.  */
    sigemptyset (&emptyset);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]