-
-
Notifications
You must be signed in to change notification settings - Fork 201
fix: mask signal during CHAIN_AT_START to survive chained handler re-raises #1572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
91afd1a
ab26763
66b86a6
b25f91d
57a447a
986a153
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| #include <limits.h> | ||
| #ifdef SENTRY_PLATFORM_UNIX | ||
| # include <poll.h> | ||
| # include <sys/syscall.h> | ||
| #endif | ||
| #include <string.h> | ||
|
|
||
|
|
@@ -1563,6 +1564,14 @@ process_ucontext(const sentry_ucontext_t *uctx) | |
| uintptr_t ip = get_instruction_pointer(uctx); | ||
| uintptr_t sp = get_stack_pointer(uctx); | ||
|
|
||
| // Mask the signal so SA_NODEFER doesn't let re-raises from the chained | ||
| // handler to kill the process before we regain control. | ||
| sigset_t mask, old_mask; | ||
| sigemptyset(&mask); | ||
| sigaddset(&mask, uctx->signum); | ||
| // raw syscall to bypass libsigchain on Android | ||
| syscall(SYS_rt_sigprocmask, SIG_BLOCK, &mask, &old_mask, _NSIG / 8); | ||
|
|
||
| // invoke the previous handler (typically the CLR/Mono | ||
| // signal-to-managed-exception handler) | ||
| invoke_signal_handler( | ||
|
|
@@ -1578,6 +1587,20 @@ process_ucontext(const sentry_ucontext_t *uctx) | |
| return; | ||
| } | ||
|
|
||
| // restore our handler | ||
sentry[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| struct sigaction current; | ||
| sigaction(uctx->signum, NULL, ¤t); | ||
| if (current.sa_handler == SIG_DFL) { | ||
| sigaction(uctx->signum, &g_sigaction, NULL); | ||
| } | ||
|
|
||
| // consume pending signal | ||
| struct timespec timeout = { 0, 0 }; | ||
| syscall(SYS_rt_sigtimedwait, &mask, NULL, &timeout, _NSIG / 8); | ||
|
Comment on lines
+1598
to
+1599
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The function returns early if the chained handler modifies Suggested FixBefore the early Prompt for AI Agent |
||
|
|
||
| // unmask | ||
| syscall(SYS_rt_sigprocmask, SIG_SETMASK, &old_mask, NULL, _NSIG / 8); | ||
|
|
||
| // return from runtime handler; continue processing the crash on the | ||
| // signal thread until the worker takes over | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raw syscall buffer overflow on 32-bit Android
High Severity
On 32-bit Android (LP32), bionic's
sigset_tis only 4 bytes, but_NSIG / 8evaluates to 8. The rawsyscall(SYS_rt_sigprocmask, SIG_BLOCK, &mask, &old_mask, _NSIG / 8)tells the kernel to write 8 bytes into the 4-byteold_maskbuffer, causing a stack buffer overflow. The project explicitly targetsarmeabi-v7aandx86(32-bit ABIs). Bionic's libc wrapper normally handles this size mismatch via an internalkernel_sigset_tunion, but the raw syscall bypasses that conversion.Additional Locations (2)
src/backends/sentry_backend_inproc.c#L1598-L1599src/backends/sentry_backend_inproc.c#L1601-L1602