bug-libsigsegv
[Top][All Lists]
Advanced

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

[Bug-libsigsegv] Re: [PATCH] More robust detection of powerpc64-unknown-


From: Bruno Haible
Subject: [Bug-libsigsegv] Re: [PATCH] More robust detection of powerpc64-unknown-linux-gnu failure.
Date: Mon, 25 Oct 2010 00:16:03 +0200
User-agent: KMail/1.9.9

Hi Eric,

> What do you think of this patch?  On the powerpc64 machine I was testing
> on, where CFLAGS=-O2 somehow makes the stack usage go a lot higher than
> CFLAGS=-O1, this changes the failure from a hard-to-diagnose SIGILL:
> 
> Starting recursion pass 1.
> /bin/sh: line 5: 15944 Illegal instruction     (core dumped) ${dir}$tst
> FAIL: stackoverflow1
> 
> to a much nicer:
> 
> Starting recursion pass 1.
> Stack overflow 1 caught.
> Starting recursion pass 2.
> Stack overflow 2 caught.
> alternate stack was exceeded!
> FAIL: stackoverflow1

Very nice! And it diagnoses the problem also on x86_64, if I decrease
SIGSTKSZ below 4 KB.

I committed your patch, with a couple of modifications:
  - Apply the changes also to 3 other tests,
  - Avoid code duplication by moving the code to a separate file,
    altstack.h.
  - Do the proper thing to get 'uintptr_t'. AC_TYPE_UINTPTR_T doesn't
    arrange for <stdint.h> to exist.
  - Change the verification step so that it also prints by how many bytes
    the alternate stack area was exceeded.


2010-10-24  Eric Blake  <address@hidden>
            Bruno Haible  <address@hidden>

        Enhance the tests to detect overflow of the alternate stack.
        * tests/altstack.h: New file.
        * tests/Makefile.am (EXTRA_DIST): Add altstack.h.
        * configure.ac: Invoke AC_TYPE_UINTPTR_T.
        * tests/stackoverflow1.c: Include altstack.h.
        (SIGSTKSZ): Remove definition.
        (mystack): Remove definition.
        (main): Invoke prepare_alternate_stack and
        check_alternate_stack_no_overflow.
        * tests/stackoverflow2.c: Likewise.
        * tests/efault2.c: Likewise.
        * tests/efault3.c: Likewise.

--- configure.ac.orig   Sun Oct 24 20:59:00 2010
+++ configure.ac        Sun Oct 24 18:10:57 2010
@@ -939,7 +939,6 @@
 
 dnl ======================= Done with CFG_HANDLER fully =======================
 
-
 dnl Test whether to enable Cygwin specific tests.
 AM_CONDITIONAL([CYGWIN],
   [case "$host_os" in
@@ -967,6 +966,10 @@
 fi
 
 
+dnl Test for features used in tests.
+AC_TYPE_UINTPTR_T
+
+
 { echo; echo "${term_bold}Build Parameters:${term_norm}"; } >& AS_MESSAGE_FD
 
 dnl Relocatability is a nop for this package.
--- tests/Makefile.am.orig      Sun Oct 24 20:59:00 2010
+++ tests/Makefile.am   Sun Oct 24 19:25:15 2010
@@ -1,5 +1,5 @@
 ## Makefile for libsigsegv/tests.
-## Copyright (C) 2002-2003, 2008-2009 Bruno Haible <address@hidden>
+## Copyright (C) 2002-2003, 2008-2010 Bruno Haible <address@hidden>
 ##
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 
 TESTS = sigsegv1 sigsegv2 sigsegv3 stackoverflow1 stackoverflow2
 
-EXTRA_DIST = mmaputil.h
+EXTRA_DIST = mmaputil.h altstack.h
 
 INCLUDES = -I../src
 DEFS = @DEFS@
Changing permissions from . to 100644
--- tests/altstack.h.orig       Tue Apr 14 12:31:40 2009
+++ tests/altstack.h    Sun Oct 24 19:42:55 2010
@@ -0,0 +1,67 @@
+/* Some auxiliary stuff for defining an alternate stack.
+   Copyright (C) 2010  Eric Blake <address@hidden>
+   Copyright (C) 2010  Bruno Haible <address@hidden>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <string.h> /* for memset */
+
+/* Get uintptr_t.  */
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#ifndef SIGSTKSZ
+# define SIGSTKSZ 16384
+#endif
+
+/* glibc says: Users should use SIGSTKSZ as the size of user-supplied
+   buffers.  We want to detect stack overflow of the alternate stack
+   in a nicer manner than just crashing, so we overallocate in
+   comparison to what we hand libsigsegv.  Also, we intentionally hand
+   an unaligned pointer, to ensure the alternate stack still ends up
+   aligned.  */
+#define MYSTACK_CRUMPLE_ZONE 8192
+char mystack_storage[SIGSTKSZ + 2 * MYSTACK_CRUMPLE_ZONE + 31];
+char *mystack; /* SIGSTKSZ bytes in the middle of storage. */
+
+static void
+prepare_alternate_stack (void)
+{
+  memset (mystack_storage, 's', sizeof mystack_storage);
+  mystack = (char *) ((uintptr_t) (mystack_storage + MYSTACK_CRUMPLE_ZONE) | 
31);
+}
+
+static void
+check_alternate_stack_no_overflow (void)
+{
+  unsigned int i;
+
+  for (i = MYSTACK_CRUMPLE_ZONE; i > 0; i--)
+    if (*(mystack - i) != 's')
+      {
+        printf ("Alternate stack was exceeded by %u bytes!!\n", i);
+        exit (1);
+      }
+  for (i = MYSTACK_CRUMPLE_ZONE; i > 0; i--)
+    if (*(mystack + SIGSTKSZ - 1 + i) != 's')
+      {
+        printf ("Alternate stack was exceeded by %u bytes!!\n", i);
+        exit (1);
+      }
+}
--- tests/efault2.c.orig        Sun Oct 24 20:59:00 2010
+++ tests/efault2.c     Sun Oct 24 19:15:40 2010
@@ -1,6 +1,6 @@
 /* Test that libsigsegv does not interfere with fault handling inside
    system calls.
-   Copyright (C) 2009  Eric Blake <address@hidden>
+   Copyright (C) 2009-2010  Eric Blake <address@hidden>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,9 +30,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#ifndef SIGSTKSZ
-# define SIGSTKSZ 16384
-#endif
+#include "altstack.h"
 
 /* A NULL pointer.
    If we were to use a literal NULL, gcc would give a warning on glibc systems:
@@ -47,10 +45,6 @@
   abort ();
 }
 
-/* glibc says: Users should use SIGSTKSZ as the size of user-supplied
-   buffers.  */
-char mystack[SIGSTKSZ];
-
 int
 main ()
 {
@@ -61,9 +55,11 @@
       exit (1);
     }
 
+  /* Prepare the storage for the alternate stack.  */
+  prepare_alternate_stack ();
+
   /* Install the stack overflow handler.  */
-  if (stackoverflow_install_handler (&handler, mystack, sizeof (mystack))
-      < 0)
+  if (stackoverflow_install_handler (&handler, mystack, SIGSTKSZ) < 0)
     exit (2);
 
   /* Test that the library does not interfere with OS faults.  */
@@ -73,6 +69,9 @@
       exit (1);
     }
 
+  /* Validate that the alternate stack did not overflow.  */
+  check_alternate_stack_no_overflow ();
+
   /* Test passed!  */
   printf ("Test passed.\n");
   return 0;
--- tests/efault3.c.orig        Sun Oct 24 20:59:00 2010
+++ tests/efault3.c     Sun Oct 24 19:15:41 2010
@@ -1,6 +1,6 @@
 /* Test that libsigsegv does not interfere with fault handling inside
    system calls.
-   Copyright (C) 2009  Eric Blake <address@hidden>
+   Copyright (C) 2009-2010  Eric Blake <address@hidden>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,9 +30,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#ifndef SIGSTKSZ
-# define SIGSTKSZ 16384
-#endif
+#include "altstack.h"
 
 /* A NULL pointer.
    If we were to use a literal NULL, gcc would give a warning on glibc systems:
@@ -55,10 +53,6 @@
   abort ();
 }
 
-/* glibc says: Users should use SIGSTKSZ as the size of user-supplied
-   buffers.  */
-char mystack[SIGSTKSZ];
-
 int
 main ()
 {
@@ -69,9 +63,12 @@
       exit (1);
     }
 
+  /* Prepare the storage for the alternate stack.  */
+  prepare_alternate_stack ();
+
   /* Install the stack overflow handler.  */
   if (stackoverflow_install_handler (&stackoverflow_handler,
-                                     mystack, sizeof (mystack))
+                                     mystack, SIGSTKSZ)
       < 0)
     exit (2);
 
@@ -86,6 +83,9 @@
       exit (1);
     }
 
+  /* Validate that the alternate stack did not overflow.  */
+  check_alternate_stack_no_overflow ();
+
   /* Test passed!  */
   printf ("Test passed.\n");
   return 0;
--- tests/stackoverflow1.c.orig Sun Oct 24 20:59:00 2010
+++ tests/stackoverflow1.c      Sun Oct 24 19:15:40 2010
@@ -1,5 +1,6 @@
 /* Test the stack overflow handler.
-   Copyright (C) 2002-2006, 2008  Bruno Haible <address@hidden>
+   Copyright (C) 2002-2006, 2008, 2010  Bruno Haible <address@hidden>
+   Copyright (C) 2010 Eric Blake <address@hidden>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -41,9 +42,7 @@
 # include <sys/time.h>
 # include <sys/resource.h>
 #endif
-#ifndef SIGSTKSZ
-# define SIGSTKSZ 16384
-#endif
+#include "altstack.h"
 
 jmp_buf mainloop;
 sigset_t mainsigset;
@@ -88,10 +87,6 @@
   return *recurse_1 (n, &n);
 }
 
-/* glibc says: Users should use SIGSTKSZ as the size of user-supplied
-   buffers.  */
-char mystack[SIGSTKSZ];
-
 int
 main ()
 {
@@ -106,13 +101,16 @@
   setrlimit (RLIMIT_STACK, &rl);
 #endif
 
+  /* Prepare the storage for the alternate stack.  */
+  prepare_alternate_stack ();
+
   /* Install the stack overflow handler.  */
   if (stackoverflow_install_handler (&stackoverflow_handler,
-                                     mystack, sizeof (mystack))
+                                     mystack, SIGSTKSZ)
       < 0)
     exit (2);
   stack_lower_bound = mystack;
-  stack_upper_bound = mystack + sizeof (mystack) - 1;
+  stack_upper_bound = mystack + SIGSTKSZ - 1;
 
   /* Save the current signal mask.  */
   sigemptyset (&emptyset);
@@ -133,6 +131,9 @@
       abort ();
     }
 
+  /* Validate that the alternate stack did not overflow.  */
+  check_alternate_stack_no_overflow ();
+
   printf ("Test passed.\n");
   exit (0);
 }
--- tests/stackoverflow2.c.orig Sun Oct 24 20:59:00 2010
+++ tests/stackoverflow2.c      Sun Oct 24 19:15:40 2010
@@ -1,5 +1,6 @@
 /* Test that stack overflow and SIGSEGV are correctly distinguished.
    Copyright (C) 2002-2006, 2008  Bruno Haible <address@hidden>
+   Copyright (C) 2010 Eric Blake <address@hidden>
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -42,9 +43,7 @@
 # include <sys/time.h>
 # include <sys/resource.h>
 #endif
-#ifndef SIGSTKSZ
-# define SIGSTKSZ 16384
-#endif
+#include "altstack.h"
 
 jmp_buf mainloop;
 sigset_t mainsigset;
@@ -109,10 +108,6 @@
   return *recurse_1 (n, &n);
 }
 
-/* glibc says: Users should use SIGSTKSZ as the size of user-supplied
-   buffers.  */
-char mystack[SIGSTKSZ];
-
 int
 main ()
 {
@@ -128,9 +123,12 @@
   setrlimit (RLIMIT_STACK, &rl);
 #endif
 
+  /* Prepare the storage for the alternate stack.  */
+  prepare_alternate_stack ();
+
   /* Install the stack overflow handler.  */
   if (stackoverflow_install_handler (&stackoverflow_handler,
-                                     mystack, sizeof (mystack))
+                                     mystack, SIGSTKSZ)
       < 0)
     exit (2);
 
@@ -184,6 +182,9 @@
       abort ();
     }
 
+  /* Validate that the alternate stack did not overflow.  */
+  check_alternate_stack_no_overflow ();
+
   printf ("Test passed.\n");
   exit (0);
 }



reply via email to

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