-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Add informational note to user-signalled SIGSEGV
#59275
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?
Conversation
If we hit a segfault from a user-triggered SIGSEGV, that usually means that someone has tampered with our signal handlers (as in JuliaInterop/Clang.jl#549). This will not help if the signal handler was dropped on the floor or intercepted by another application without forwarding, but it will at least be useful to detect bad signal forwarding from another library.
Avoid using 0, which is a meaningful `si_code` on Linux (SI_USER).
a50445f to
7471032
Compare
|
Oh, maybe this would help with PyCall and PythonCall, there are often segfaults because of multithreaded GC interacting badly with the python process. |
| jl_safe_printf("\n[%d] signal %d: %s\n", getpid(), sig, strsignal(sig)); | ||
| #ifdef _OS_LINUX_ | ||
| if ((sig == SIGBUS || sig == SIGSEGV) && (si_code <= 0)) | ||
| jl_safe_printf("signal came from user-land, signal handlers may be mis-configured.\n"); |
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.
| jl_safe_printf("signal came from user-land, signal handlers may be mis-configured.\n"); | |
| jl_safe_printf("signal came from userland, signal handlers may be misconfigured.\n"); |
| jl_safe_printf("\n[%d] signal %d (%d): %s\n", getpid(), sig, si_code, strsignal(sig)); | ||
| else | ||
| jl_safe_printf("\n[%d] signal %d: %s\n", getpid(), sig, strsignal(sig)); | ||
| #ifdef _OS_LINUX_ |
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.
This should also work on FreeBSD, I think
vtjnash
left a comment
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.
What does "signal came from userland" mean? Every signal comes from userland in some way (except perhaps SIGPWR, and that is very uncommon).
| else | ||
| jl_safe_printf("\n[%d] signal %d: %s\n", getpid(), sig, strsignal(sig)); | ||
| #ifdef _OS_LINUX_ | ||
| if ((sig == SIGBUS || sig == SIGSEGV) && (si_code <= 0)) |
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.
| if ((sig == SIGBUS || sig == SIGSEGV) && (si_code <= 0)) | |
| if ((sig == SIGBUS || sig == SIGSEGV) && (si_code <= 0)) # SI_FROMUSER(&si_code) |
But none of these seem really that interesting here to deserve a special comment when our signal handler is installed but gets one of these sent:
/*
* si_code values
* Digital reserves positive values for kernel-generated signals.
*/
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
#define SI_QUEUE -1 /* sent by sigqueue */
#define SI_TIMER -2 /* sent by timer expiration */
#define SI_MESGQ -3 /* sent by real time mesq state change */
#define SI_ASYNCIO -4 /* sent by AIO completion */
#define SI_SIGIO -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */
#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
#define SI_ASYNCNL -60 /* sent by glibc async name lookup completion */
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.
The main idea for the note is to detect signal forwarding that's incompatible with our use of siginfo in the segv_handler.
As far as I can tell kill, raise, sigqueue, and tgkill can all "forward" an intercepted SIGSEGV (or trigger an artificial one), but none can preserve the si_code + si_addr that we depend on to identify a safepoint-segfault from a real one.
IIUC the only forwarding that preserves a sufficient amount of the signal metadata is rt_sigqueueinfo(2) (or manually calling / chaining the signal handler, which is what the JVM does)
|
I think the goal is to distinguish a |
If we hit a segfault from a user-triggered SIGSEGV, that usually means that someone has tampered with our signal handlers (as in JuliaInterop/Clang.jl#549)
Prints as:
This will not help if the signal handler was dropped on the floor or intercepted by another application without forwarding, but it will at least be useful to detect bad signal forwarding from another library.