This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Infinite recursion avoidance for crash_signal()


Imagine if you will that some part of GCC goes insane and writes
garbage all over the bottom of the stack, the command line and
environment array, then tries to go on into kernel space, causing a
segmentation fault.  The top part of the stack is still fine, so the
kernel can invoke our nice friendly SIGSEGV-to-ICE handler.  It calls
strsignal, which calls gettext, which tries to look up the LANGUAGE
environment variable.  As the environment array has been trashed, this
causes another segfault.  Our handler is called again, and again it
calls strsignal ... infinite recursion.  Since we are setting
RLIMIT_STACK to unlimited, the program will only get killed after the
stack has consumed all available memory, with consequent unpleasant
effects on anything else running concurrently.

I observe the PCH reader doing exactly this, right now, in my testing
tree for the "mmap blacklist" patch.  This is the stack trace.  (Call
frames beyond gt_pch_restore have been destroyed, and I'm pretty sure
the arguments listed for __GI___mempcpy are bogus.)

#0  strsignal (signum=11) at strsignal.c:56
#1  0x083a7da1 in crash_signal (signo=11)
    at /home/zack/src/gcc/vanilla/gcc/toplev.c:1766
#2  <signal handler called>
#3  0x4003a260 in *__GI_getenv (name=0x4011389d "NGUAGE")
    at ../sysdeps/generic/getenv.c:93
#4  0x40034729 in guess_category_value (category=5, 
    categoryname=0x4011414c "on reset by peer") at dcigettext.c:1078
#5  0x40033e7d in __dcigettext (domainname=0x4010c53c "libc", 
    msgid1=0x40114355 "Segmentation fault", msgid2=0x0, plural=0, n=0, 
    category=5) at dcigettext.c:509
#6  0x40033a27 in __dcgettext (domainname=0x4010c53c "libc", 
    msgid=0x40114355 "Segmentation fault", category=5) at dcgettext.c:53
#7  0x4007fa74 in strsignal (signum=11) at strsignal.c:83
#8  0x083a7da1 in crash_signal (signo=11)
    at /home/zack/src/gcc/vanilla/gcc/toplev.c:1766
#9  <signal handler called>
#10 0x4003a260 in *__GI_getenv (name=0x4011389d "NGUAGE")
    at ../sysdeps/generic/getenv.c:93
#11 0x40034729 in guess_category_value (category=5, 
    categoryname=0x4011414c "on reset by peer") at dcigettext.c:1078
#12 0x40033e7d in __dcigettext (domainname=0x4010c53c "libc", 
    msgid1=0x40114355 "Segmentation fault", msgid2=0x0, plural=0, n=0, 
    category=5) at dcigettext.c:509
#13 0x40033a27 in __dcgettext (domainname=0x4010c53c "libc", 
    msgid=0x40114355 "Segmentation fault", category=5) at dcgettext.c:53
#14 0x4007fa74 in strsignal (signum=11) at strsignal.c:83
#15 0x083a7da1 in crash_signal (signo=11)
    at /home/zack/src/gcc/vanilla/gcc/toplev.c:1766
#16 <signal handler called>
#17 0x40080b01 in *__GI___mempcpy (dstpp=0x8606788, srcpp=0xbffff4a0, len=11)
    at ../sysdeps/generic/mempcpy.c:57
#18 0x40076515 in _IO_file_xsgetn (fp=0x8606788, data=0xbffff4a0, n=15077376)
    at fileops.c:1413
#19 0x40077121 in _IO_sgetn (fp=0x4011414c, data=0xbffff4a0, n=15077376)
    at genops.c:492
#20 0x4006cdc3 in _IO_fread (buf=0xbffff4a0, size=15077376, count=1, 
    fp=0x8606788) at iofread.c:44
#21 0x0826878f in gt_pch_restore (f=0x8606788)
    at /home/zack/src/gcc/vanilla/gcc/ggc-common.c:605

I do not yet know whether I broke something, but belt-and-suspenders
design for crash_signal seems like a good idea independent of whose
fault this is.  It should suffice for crash_signal to reset handling
for the signal it received, before proceeding.  That will make a
second signal terminate the program, and the driver will print a
(not quite as informative) ICE message, so we're not losing much.
Worst case we cycle through all the "core dump" signals before
getting shut down.

zw

        * toplev.c (crash_signal): Reset handling for received signal
        to SIG_DFL.

===================================================================
Index: toplev.c
--- toplev.c	1 Jun 2003 16:04:53 -0000	1.761
+++ toplev.c	2 Jun 2003 02:45:42 -0000
@@ -1758,11 +1758,13 @@ floor_log2_wide (unsigned HOST_WIDE_INT 
 }
 
 /* Handler for fatal signals, such as SIGSEGV.  These are transformed
-   into ICE messages, which is much more user friendly.  */
+   into ICE messages, which is much more user friendly.  In case the
+   error printer crashes, reset the signal to prevent infinite recursion.  */
 
 static void
 crash_signal (int signo)
 {
+  signal (signo, SIG_DFL);
   internal_error ("%s", strsignal (signo));
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]