https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85334
Bug ID: 85334 Summary: Shadow stack isn't unwound properly through signal handler Product: gcc Version: 8.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libgcc Assignee: unassigned at gcc dot gnu.org Reporter: hjl.tools at gmail dot com Blocks: 81652 Target Milestone: --- Target: x86_64-*-*, i?86-*-* 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> <<<< Extra 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. I am testing this patch: diff --git a/libgcc/config/i386/shadow-stack-unwind.h b/libgcc/config/i386/shadow-stack-unwind.h index 40f48df2aec..a32f3e74b52 100644 --- a/libgcc/config/i386/shadow-stack-unwind.h +++ b/libgcc/config/i386/shadow-stack-unwind.h @@ -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++ diff --git a/libgcc/unwind-generic.h b/libgcc/unwind-generic.h index b5e3568e1bc..639c96f438e 100644 --- a/libgcc/unwind-generic.h +++ b/libgcc/unwind-generic.h @@ -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 */ diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 68c08964d30..b49f8797009 100644 --- a/libgcc/unwind.inc +++ b/libgcc/unwind.inc @@ -72,8 +72,9 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, /* Don't let us unwind past the handler context. */ gcc_assert (!match_handler); + _Unwind_Frames_Increment (context, frames); + uw_update_context (context, &fs); - frames++; } *frames_p = frames; @@ -187,10 +188,11 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, return _URC_FATAL_PHASE2_ERROR; } + _Unwind_Frames_Increment (context, frames); + /* Update cur_context to describe the same frame as fs, and discard the previous context if necessary. */ uw_advance_context (context, &fs); - frames++; } *frames_p = frames; Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81652 [Bug 81652] [meta-bug] -fcf-protection=full -mcet bugs