[llvm-branch-commits] [compiler-rt] [SafeStack] Intercept signal handlers (PR #196970)

Vitaly Buka via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Oct 4 23:21:11 PDT 2026


================
@@ -304,13 +378,72 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread,
 }
 
 // We are intercepting sigaction in order to keep note of the set sigaction and
-// overwrite it our own function to execute the switching if the unsafe stack
-// pointer before and after the signal is handled.
-// In this version, we are simply making sure the interceptor is functional.
+// overwrite it with 'signal_handler_interceptor()/signal_action_interceptor()'
+// in order to execute custom before and after running the actual signal
+// handler (to switch to the sigalt_unsafe_stack and back). The interception is
+// only done for signal handlers that actually use the sigaltstack.
+// The code here, is largely inspired by the way MSan does intercept signal
+// handlers in compiler-rt/lib/msan/msan_interceptors.cpp.
 // sigaction is required to be async-signal-safe.
 INTERCEPTOR(int, sigaction, int sig, const struct sigaction* act,
             struct sigaction* oldact) {
-  return REAL(sigaction)(sig, act, oldact);
+  if (!act || !sigactions)
+    return REAL(sigaction)(sig, act, oldact);
+  if (!(act->sa_flags & SA_ONSTACK))
+    return REAL(sigaction)(sig, act, oldact);
+
+  int res;
+  sigactions_mu.Lock();
+
+  void* old_cb = (void*)atomic_load(&sigactions[sig], memory_order_relaxed);
+  struct sigaction new_act;
+  struct sigaction* pnew_act = &new_act;
+  memcpy(pnew_act, act, sizeof(struct sigaction));
+  uptr cb;
+  uptr new_cb;
+
+  // We first fetch the original sigaction/handler passed to sigaction.
+  if (pnew_act->sa_flags & SA_SIGINFO) {
+    cb = (uptr)pnew_act->sa_sigaction;
+    new_cb = (uptr)signal_action_interceptor;
+  } else {
+    cb = (uptr)pnew_act->sa_handler;
+    new_cb = (uptr)signal_handler_interceptor;
+  }
+
+  if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
+    // We keep sigactions mapped without write permissions to avoid an arbitrary
+    // write trivially corrupting a signal handler pointer.
----------------
vitalybuka wrote:

Does GLIBC mprotects that? If not, why safe stack should?

https://github.com/llvm/llvm-project/pull/196970


More information about the llvm-branch-commits mailing list