libgcc/CET: Skip signal frames when unwinding shadow stack
authorH.J. Lu <hongjiu.lu@intel.com>
Thu, 19 Apr 2018 17:05:39 +0000 (17:05 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Thu, 19 Apr 2018 17:05:39 +0000 (10:05 -0700)
When -fcf-protection -mcet is used, I got

FAIL: g++.dg/eh/sighandle.C

(gdb) bt
 #0  _Unwind_RaiseException (exc=exc@entry=0x416ed0)
    at /export/gnu/import/git/sources/gcc/libgcc/unwind.inc:140
 #1  0x00007ffff7d9936b in __cxxabiv1::__cxa_throw (obj=<optimized out>,
    tinfo=0x403dd0 <typeinfo for int@@CXXABI_1.3>, dest=0x0)
    at /export/gnu/import/git/sources/gcc/libstdc++-v3/libsupc++/eh_throw.cc:90
 #2  0x0000000000401255 in sighandler (signo=11, si=0x7fffffffd6f8,
    uc=0x7fffffffd5c0)
    at /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.dg/eh/sighandle.C:9
 #3  <signal handler called> <<<< Signal frame which isn't on shadow stack
 #4  dosegv ()
    at /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.dg/eh/sighandle.C:14
 #5  0x00000000004012e3 in main ()
    at /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.dg/eh/sighandle.C:30
(gdb) p frames
$6 = 5
(gdb)

frame count should be 4, not 5.  This patch skips signal frames when
unwinding shadow stack.

gcc/testsuite/

PR libgcc/85334
* g++.dg/torture/pr85334.C: New test.

libgcc/

PR libgcc/85334
* unwind-generic.h (_Unwind_Frames_Increment): New.
* config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment):
Likewise.
* unwind.inc (_Unwind_RaiseException_Phase2): Increment frame
count with _Unwind_Frames_Increment.
(_Unwind_ForcedUnwind_Phase2): Likewise.

From-SVN: r259502

gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr85334.C [new file with mode: 0644]
libgcc/ChangeLog
libgcc/config/i386/shadow-stack-unwind.h
libgcc/unwind-generic.h
libgcc/unwind.inc

index 62dec37421817f4afb7156450aeaea6a4ba6429b..e7b9547c1a41502eff9a4f1dcf72dbdeb182a85c 100644 (file)
@@ -1,3 +1,8 @@
+2018-04-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR libgcc/85334
+       * g++.dg/torture/pr85334.C: New test.
+
 2018-04-19  Jonathan Wakely  <jwakely@redhat.com>
 
        PR c++/85464 - missing location for -Wignored-qualifiers diagnostic
diff --git a/gcc/testsuite/g++.dg/torture/pr85334.C b/gcc/testsuite/g++.dg/torture/pr85334.C
new file mode 100644 (file)
index 0000000..0809781
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-do run { target { i?86-*-linux* i?86-*-gnu* x86_64-*-linux* } } }
+// { dg-require-effective-target cet }
+// { dg-additional-options "-fexceptions -fnon-call-exceptions -fcf-protection -mcet" }
+
+#include <signal.h>
+#include <stdlib.h>
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+  throw (5);
+}
+
+char * dosegv ()
+{    
+  * ((volatile int *)0) = 12;
+  return 0;
+}
+
+int main ()
+{
+  struct sigaction sa;
+  int status;
+
+  sa.sa_sigaction = sighandler;
+  sa.sa_flags = SA_SIGINFO;
+    
+  status = sigaction (SIGSEGV, & sa, NULL);
+  status = sigaction (SIGBUS, & sa, NULL);
+
+  try {
+    dosegv ();
+  }
+  catch (int x) {
+    return (x != 5);
+  }
+
+  return 1;
+}
index 674d2041bd762dcbc0532c0ef9dc0d1a7d3d9e6e..8a645c80e3d0e9fa6470b37d13b01fbe50bad0c5 100644 (file)
@@ -1,3 +1,13 @@
+2018-04-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR libgcc/85334
+       * unwind-generic.h (_Unwind_Frames_Increment): New.
+       * config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment):
+       Likewise.
+       * unwind.inc (_Unwind_RaiseException_Phase2): Increment frame
+       count with _Unwind_Frames_Increment.
+       (_Unwind_ForcedUnwind_Phase2): Likewise.
+
 2018-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR libgcc/85379
index 40f48df2aecdc1c1836cf55853ef13cbde219f32..a32f3e74b52dffd092eab90cfc9dd76de0609840 100644 (file)
@@ -49,3 +49,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
        }                                       \
     }                                          \
     while (0)
+
+/* Increment frame count.  Skip signal frames.  */
+#undef _Unwind_Frames_Increment
+#define _Unwind_Frames_Increment(context, frames) \
+  if (!_Unwind_IsSignalFrame (context)) frames++
index b5e3568e1bc4963c2813deffd3f49a6d8bc68ac2..639c96f438ee2f068eb89d2ffb2b09b8600b9bf7 100644 (file)
@@ -291,4 +291,7 @@ EXCEPTION_DISPOSITION _GCC_specific_handler (PEXCEPTION_RECORD, void *,
 /* Additional actions to unwind number of stack frames.  */
 #define _Unwind_Frames_Extra(frames)
 
+/* Increment frame count.  */
+#define _Unwind_Frames_Increment(context, frames) frames++
+
 #endif /* unwind.h */
index 68c08964d30045d93d3c0d6be574921d6db0d19e..19a8e4f6c80f498f917306c36f9546978a3e40ad 100644 (file)
@@ -73,7 +73,7 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
       gcc_assert (!match_handler);
 
       uw_update_context (context, &fs);
-      frames++;
+      _Unwind_Frames_Increment (context, frames);
     }
 
   *frames_p = frames;
@@ -190,7 +190,7 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
       /* Update cur_context to describe the same frame as fs, and discard
         the previous context if necessary.  */
       uw_advance_context (context, &fs);
-      frames++;
+      _Unwind_Frames_Increment (context, frames);
     }
 
   *frames_p = frames;