From a72739ab5a9c40788557dbc4084c275b5a62a657 Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Wed, 7 Feb 2018 18:44:10 +0300 Subject: [PATCH 4/4] ExecuteHandlerOnOriginalStack: handle case when it is called on original stack. If ExecuteHandlerOnOriginalStack is called on original stack (for example, if segmentation fault occurs in native application's thread that hasn't alternate signal stack) we should use faultSp from its frame otherwise stackframe of the caller function will be corrupted. --- src/pal/src/arch/amd64/signalhandlerhelper.cpp | 20 ++++++++++++++++++-- src/pal/src/arch/arm/signalhandlerhelper.cpp | 18 +++++++++++++++++- src/pal/src/arch/arm64/signalhandlerhelper.cpp | 19 ++++++++++++++++++- src/pal/src/arch/i386/signalhandlerhelper.cpp | 18 +++++++++++++++++- 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/pal/src/arch/amd64/signalhandlerhelper.cpp b/src/pal/src/arch/amd64/signalhandlerhelper.cpp index 8789f5a..803479c 100644 --- a/src/pal/src/arch/amd64/signalhandlerhelper.cpp +++ b/src/pal/src/arch/amd64/signalhandlerhelper.cpp @@ -27,7 +27,23 @@ Parameters : void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint) { ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext); + size_t faultSp; + + // check whether this function is called on alternate stack or not. In the second case we already + // on original stack and we should use faultSp from this frame otherwise stackframe of the caller + // function will be corrupted. + char fakeStackFrame[128 /* redzone */ + 16 /* aligment */ + 4 * sizeof(size_t) /* registers */]; + stack_t oss; + int st = sigaltstack(NULL, &oss); + if ((st == 0) && ((oss.ss_flags == SS_DISABLE) || + ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp))) + { + faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)]; + } + else + { + faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext); + } _ASSERTE(IS_ALIGNED(faultSp, 8)); @@ -58,7 +74,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, // We don't care about the other registers state since the stack unwinding restores // them for the target frame directly from the signal context. context2.Rsp = (size_t)sp; - context2.Rbx = (size_t)faultSp; + context2.Rbx = (size_t)MCREG_Rsp(ucontext->uc_mcontext); context2.Rbp = (size_t)fp; context2.Rip = (size_t)signal_handler_worker; context2.Rdi = code; diff --git a/src/pal/src/arch/arm/signalhandlerhelper.cpp b/src/pal/src/arch/arm/signalhandlerhelper.cpp index 3936204..fbf33e3 100644 --- a/src/pal/src/arch/arm/signalhandlerhelper.cpp +++ b/src/pal/src/arch/arm/signalhandlerhelper.cpp @@ -27,7 +27,23 @@ Parameters : void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint) { ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + size_t faultSp; + + // check whether this function is called on alternate stack or not. In the second case we already + // on original stack and we should use faultSp from this frame otherwise stackframe of the caller + // function will be corrupted. + char fakeStackFrame[8 /* redzone */ + 8 /* aligment */ + sizeof(ucontext->uc_mcontext) + 8 /* registers */]; + stack_t oss; + int st = sigaltstack(NULL, &oss); + if ((st == 0) && ((oss.ss_flags == SS_DISABLE) || + ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp))) + { + faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)]; + } + else + { + faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + } _ASSERTE(IS_ALIGNED(faultSp, 4)); diff --git a/src/pal/src/arch/arm64/signalhandlerhelper.cpp b/src/pal/src/arch/arm64/signalhandlerhelper.cpp index c35c629..958b8af 100644 --- a/src/pal/src/arch/arm64/signalhandlerhelper.cpp +++ b/src/pal/src/arch/arm64/signalhandlerhelper.cpp @@ -27,7 +27,24 @@ Parameters : void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint) { ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + size_t faultSp; + + // check whether this function is called on alternate stack or not. In the second case we already + // on original stack and we should use faultSp from this frame otherwise stackframe of the caller + // function will be corrupted. + char fakeStackFrame[128 /* redzone */ + 16 /* aligment */ + 3 * sizeof(size_t) /* registers */]; + stack_t oss; + int st = sigaltstack(NULL, &oss); + if ((st == 0) && ((oss.ss_flags == SS_DISABLE) || + ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp))) + { + faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)]; + } + else + { + faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + } + _ASSERTE(IS_ALIGNED(faultSp, 8)); size_t fakeFrameReturnAddress; diff --git a/src/pal/src/arch/i386/signalhandlerhelper.cpp b/src/pal/src/arch/i386/signalhandlerhelper.cpp index a7d418a..d534f96 100644 --- a/src/pal/src/arch/i386/signalhandlerhelper.cpp +++ b/src/pal/src/arch/i386/signalhandlerhelper.cpp @@ -27,7 +27,23 @@ Parameters : void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint) { ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext); + size_t faultSp; + + // check whether this function is called on alternate stack or not. In the second case we already + // on original stack and we should use faultSp from this frame otherwise stackframe of the caller + // function will be corrupted. + char fakeStackFrame[16 /* aligment */ + 10 * sizeof(size_t) /* registers */]; + stack_t oss; + int st = sigaltstack(NULL, &oss); + if ((st == 0) && ((oss.ss_flags == SS_DISABLE) || + ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp))) + { + faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)]; + } + else + { + faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext); + } _ASSERTE(IS_ALIGNED(faultSp, 4)); -- 2.7.4