diff options
author | Takashi Yano <takashi.yano@nifty.ne.jp> | 2025-03-12 09:52:44 +0900 |
---|---|---|
committer | Takashi Yano <takashi.yano@nifty.ne.jp> | 2025-03-15 00:53:33 +0900 |
commit | 0210c77311ae59a7959f413c8ca9d1fc624ef373 (patch) | |
tree | db37b18d08939e3d48d2e9e0feff0a412dec32b7 | |
parent | 9b02451f6e4ad1feddb998e136ac7108bda6c948 (diff) | |
download | newlib-0210c77311ae59a7959f413c8ca9d1fc624ef373.zip newlib-0210c77311ae59a7959f413c8ca9d1fc624ef373.tar.gz newlib-0210c77311ae59a7959f413c8ca9d1fc624ef373.tar.bz2 |
Cygwin: signal: Use context locally copied in call_signal_handler()
If the signal handler is called from inside of another signal handler,
_cygtls::context may be destroyed by call_signal_handler() newly called.
To avoid this situation, this patch used context locally copied in
call_signal_handler().
Addresses: https://cygwin.com/pipermail/cygwin-patches/2025q1/013483.html
Fixes: 9043956ce859 ("Only construct ucontext for SA_SIGINFO signal handlers")
Reported-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
-rw-r--r-- | winsup/cygwin/exceptions.cc | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 95904e9..86523af 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1660,6 +1660,8 @@ altstack_wrapper (int sig, siginfo_t *siginfo, ucontext_t *sigctx, int _cygtls::call_signal_handler () { + ucontext_t context1 = context; + int this_sa_flags = SA_RESTART; while (1) { @@ -1697,10 +1699,10 @@ _cygtls::call_signal_handler () /* Only make a context for SA_SIGINFO handlers */ if (this_sa_flags & SA_SIGINFO) { - context.uc_link = 0; - context.uc_flags = 0; + context1.uc_link = 0; + context1.uc_flags = 0; if (thissi.si_cyg) - memcpy (&context.uc_mcontext, + memcpy (&context1.uc_mcontext, ((cygwin_exception *) thissi.si_cyg)->context (), sizeof (CONTEXT)); else @@ -1710,13 +1712,13 @@ _cygtls::call_signal_handler () from sigdelayed, fix the instruction pointer accordingly. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" - RtlCaptureContext ((PCONTEXT) &context.uc_mcontext); + RtlCaptureContext ((PCONTEXT) &context1.uc_mcontext); #pragma GCC diagnostic pop - __unwind_single_frame ((PCONTEXT) &context.uc_mcontext); + __unwind_single_frame ((PCONTEXT) &context1.uc_mcontext); if (stackptr > stack) { #ifdef __x86_64__ - context.uc_mcontext.rip = retaddr (); + context1.uc_mcontext.rip = retaddr (); #else #error unimplemented for this target #endif @@ -1727,30 +1729,30 @@ _cygtls::call_signal_handler () && !_my_tls.altstack.ss_flags && _my_tls.altstack.ss_sp) { - context.uc_stack = _my_tls.altstack; - context.uc_stack.ss_flags = SS_ONSTACK; + context1.uc_stack = _my_tls.altstack; + context1.uc_stack.ss_flags = SS_ONSTACK; } else { - context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase; - context.uc_stack.ss_flags = 0; + context1.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase; + context1.uc_stack.ss_flags = 0; if (!NtCurrentTeb ()->DeallocationStack) - context.uc_stack.ss_size + context1.uc_stack.ss_size = (uintptr_t) NtCurrentTeb ()->Tib.StackLimit - (uintptr_t) NtCurrentTeb ()->Tib.StackBase; else - context.uc_stack.ss_size + context1.uc_stack.ss_size = (uintptr_t) NtCurrentTeb ()->DeallocationStack - (uintptr_t) NtCurrentTeb ()->Tib.StackBase; } - context.uc_sigmask = context.uc_mcontext.oldmask = this_oldmask; + context1.uc_sigmask = context1.uc_mcontext.oldmask = this_oldmask; - context.uc_mcontext.cr2 = (thissi.si_signo == SIGSEGV - || thissi.si_signo == SIGBUS) - ? (uintptr_t) thissi.si_addr : 0; + context1.uc_mcontext.cr2 = (thissi.si_signo == SIGSEGV + || thissi.si_signo == SIGBUS) + ? (uintptr_t) thissi.si_addr : 0; - thiscontext = &context; - context_copy = context; + thiscontext = &context1; + context_copy = context1; } int this_errno = saved_errno; @@ -1863,10 +1865,11 @@ _cygtls::call_signal_handler () incyg = true; set_signal_mask (_my_tls.sigmask, (this_sa_flags & SA_SIGINFO) - ? context.uc_sigmask : this_oldmask); + ? context1.uc_sigmask : this_oldmask); if (this_errno >= 0) set_errno (this_errno); } + context = context1; /* FIXME: Since 2011 this return statement always returned 1 (meaning SA_RESTART is effective) if the thread we're running in is not the |