[Top][All Lists]
[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);
Re: c-stack and Irix - gnulib, Eric Blake, 2008/09/23