summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <[email protected]>2024-04-03 23:14:52 +0900
committerNobuyoshi Nakada <[email protected]>2024-04-03 23:14:52 +0900
commitf928e60d41314a9aad2d9629114bb3ae57f51096 (patch)
treeac575311fb153385fa3f8ad470c648dd044cbb40 /signal.c
parent4960a598d6bc42adcfd488c7f455b2defcdc8161 (diff)
Check if a fatal signal is from kernel
On Linux, `siginfo_t` uses a union for each `si_code`, and the field corresponding to `si_pid` does not belong to the `_sigfault` field for SIGSEGV. It actually overlaps the `si_addr` field, which is usually non-zero on stack overflow. https://github.com/ruby/ruby/pull/10201#issuecomment-2034723244
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/signal.c b/signal.c
index 636574ba07..48b0d4488e 100644
--- a/signal.c
+++ b/signal.c
@@ -867,16 +867,19 @@ check_stack_overflow(int sig, const void *addr)
}
}
# endif
+
# ifdef _WIN32
# define CHECK_STACK_OVERFLOW() check_stack_overflow(sig, 0)
# else
# define FAULT_ADDRESS info->si_addr
# ifdef USE_UCONTEXT_REG
-# define CHECK_STACK_OVERFLOW() (info->si_pid ? (void)0 : check_stack_overflow(sig, (uintptr_t)FAULT_ADDRESS, ctx))
+# define CHECK_STACK_OVERFLOW_() check_stack_overflow(sig, (uintptr_t)FAULT_ADDRESS, ctx)
# else
-# define CHECK_STACK_OVERFLOW() (info->si_pid ? (void)0 : check_stack_overflow(sig, FAULT_ADDRESS))
+# define CHECK_STACK_OVERFLOW_() check_stack_overflow(sig, FAULT_ADDRESS)
# endif
# define MESSAGE_FAULT_ADDRESS " at %p", FAULT_ADDRESS
+# define SIGNAL_FROM_USER_P() ((info)->si_code == SI_USER)
+# define CHECK_STACK_OVERFLOW() (SIGNAL_FROM_USER_P() ? (void)0 : CHECK_STACK_OVERFLOW_())
# endif
#else
# define CHECK_STACK_OVERFLOW() (void)0