On Tue, Mar 27, 2018 at 8:55 AM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Tue, Mar 27, 2018 at 8:43 AM, Florian Weimer <fwei...@redhat.com> wrote: >> On 03/27/2018 01:26 PM, H.J. Lu wrote: >> >>> 2. Since shadow stack is never saved and restored by compiler, unwinder >>> in libgcc counts how many stack frame it has to unwind and uses INCSSP >>> to pop shadow stack. This can't unwind the original shadow stack when >>> the alternate shadow stack is used. _URC_NO_REASON_CANCEL >>> works only if longjmp will be used to finish stack unwinding, which is >>> the case for thread cancellation in glibc. >>> >>> Here are patches for GCC: >>> >>> >>> https://github.com/hjl-tools/gcc/commit/e9ff815941406e38fa629947af4d809b9129e860 >>> >>> and glibc: >>> >>> >>> https://github.com/hjl-tools/glibc/commit/1aec81528ab26aa8a8a7965317b6e1a8ba4526aa >>> >>> They fixed the issue. >> >> >> The patches are nice and short, but: Do they really fix the issue? They >> make cancellation work again, but they do not fix the general unwinding >> issue with alternate signal handler stacks AFAICS. > > That is true. We do support unwinding with alternate signal handler stack > using longjmp. If there is another use case of unwinding with alternate > signal > handler stack, we can investigate. If this isn't a valid use case, we > don't want > to create a very complex scheme to support it.
Here is a GCC only patch without changing glibc. If we are in alternate signal stack, don't try to unwind shadow stack. diff --git a/libgcc/config/i386/linux-unwind.h b/libgcc/config/i386/linux-unwind.h index f1f52334d8d..0e082873a5f 100644 --- a/libgcc/config/i386/linux-unwind.h +++ b/libgcc/config/i386/linux-unwind.h @@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* Unwind shadow stack for -fcf-protection -mshstk. */ #if defined __SHSTK__ && defined __CET__ +# define _Unwind_Frames_Extra_Skip_Alternate_Signal_Stack # include "config/i386/shadow-stack-unwind.h" #endif diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 68c08964d30..9fbde024135 100644 --- a/libgcc/unwind.inc +++ b/libgcc/unwind.inc @@ -152,6 +152,19 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; _Unwind_Reason_Code code, stop_code; unsigned long frames = 1; + int in_signal_stack = 0; +#ifdef _Unwind_Frames_Extra_Skip_Alternate_Signal_Stack + stack_t signal_stack; + + if (sigaltstack (NULL, &signal_stack) == 0 + && signal_stack.ss_flags == SS_ONSTACK) + { + void *stack = __builtin_frame_address (0); + if (stack >= signal_stack.ss_sp + && stack < (signal_stack.ss_sp + signal_stack.ss_size)) + in_signal_stack = 1; + } +#endif while (1) { @@ -193,6 +206,9 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, frames++; } + if (in_signal_stack) + frames = 0; + *frames_p = frames; return code; } -- H.J.