[compiler-rt] [compiler-rt][ubsan] Fix uninitted sigaction in __ubsan_install_trap_loop_detection (PR #225495)

Vy Nguyen via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 17:47:36 PDT 2026


https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/225495

>From 8998765334338eeb624b98dce75137376ca561a0 Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Tue, 22 Sep 2026 15:17:18 -0400
Subject: [PATCH] [compiler-rt][ubsan] Fix uninitted sigaction in
 __ubsan_install_trap_loop_detection

Details:

Zero-init sigaction and set SA_SIGINFO | SA_RESTART in __ubsan_install_trap_loop_detection

`__ubsan_install_trap_loop_detection` passed an uninitialized `struct sigaction` to `sigaction(SIGPROF, ...)`, leaving garbage in `sa_flags` and `sa_mask` (such as setting `SA_RESETHAND`, blocking `SIGILL`, and omitting `SA_SIGINFO`). Zero-initialize `sa` and set `sa.sa_flags = SA_SIGINFO | SA_RESTART`.
---
 compiler-rt/lib/ubsan/ubsan_loop_detect.cpp   |  3 +-
 .../TestCases/Misc/Posix/trap_loop_detect.cpp | 51 +++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 compiler-rt/test/ubsan/TestCases/Misc/Posix/trap_loop_detect.cpp

diff --git a/compiler-rt/lib/ubsan/ubsan_loop_detect.cpp b/compiler-rt/lib/ubsan/ubsan_loop_detect.cpp
index 75e9724a06f35f..59bdcb0ad3bb28 100644
--- a/compiler-rt/lib/ubsan/ubsan_loop_detect.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_loop_detect.cpp
@@ -81,8 +81,9 @@ static void SigprofHandler(int signo, siginfo_t *si, void *c) {
 }
 
 void __ubsan_install_trap_loop_detection(void) {
-  struct sigaction sa;
+  struct sigaction sa = {};
   sa.sa_sigaction = SigprofHandler;
+  sa.sa_flags = SA_SIGINFO | SA_RESTART;
   sigaction(SIGPROF, &sa, nullptr);
 
   struct itimerval timer;
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/Posix/trap_loop_detect.cpp b/compiler-rt/test/ubsan/TestCases/Misc/Posix/trap_loop_detect.cpp
new file mode 100644
index 00000000000000..8fb6ca6e432ccd
--- /dev/null
+++ b/compiler-rt/test/ubsan/TestCases/Misc/Posix/trap_loop_detect.cpp
@@ -0,0 +1,51 @@
+// REQUIRES: ubsan-standalone
+// REQUIRES: target={{(i.86|x86_64)-.*-linux.*}}
+// RUN: %clangxx -O2 -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -fsanitize-trap-loop %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+#include <assert.h>
+#include <limits.h>
+#include <sanitizer/ubsan_interface.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+__attribute__((noinline)) static void poison_stack() {
+  volatile unsigned char buf[256];
+  for (size_t i = 0; i < sizeof(buf); ++i)
+    buf[i] = 0xaa;
+}
+
+static void sigill_handler(int) {
+  const char msg[] = "CAUGHT_TRAP_LOOP_SIGILL\n";
+  write(STDERR_FILENO, msg, sizeof(msg) - 1);
+  _exit(0);
+}
+
+__attribute__((noinline)) int trigger_overflow(int a, int b) { return a + b; }
+
+int main() {
+  struct sigaction sa_ill = {};
+  sa_ill.sa_handler = sigill_handler;
+  sigaction(SIGILL, &sa_ill, nullptr);
+  poison_stack();
+  __ubsan_install_trap_loop_detection();
+
+  struct sigaction old_sa = {};
+  assert(sigaction(SIGPROF, nullptr, &old_sa) == 0);
+  assert((old_sa.sa_flags & SA_SIGINFO) != 0);
+  assert((old_sa.sa_flags & SA_RESETHAND) == 0);
+  assert(!sigismember(&old_sa.sa_mask, SIGILL));
+
+  // Verify multiple SIGPROF deliveries during normal execution do not crash
+  // (e.g. on i386 when SA_SIGINFO is missing) or reset SIGPROF to SIG_DFL
+  // (when SA_RESETHAND is set in uninitialized sa_flags).
+  raise(SIGPROF);
+  raise(SIGPROF);
+  fprintf(stderr, "SURVIVED_NORMAL_SIGPROF\n");
+
+  // Trigger a trap loop and verify SIGPROF -> __builtin_trap() -> SIGILL
+  // reaches sigill_handler without SIGILL being blocked by uninitialized sa_mask.
+  // CHECK: SURVIVED_NORMAL_SIGPROF
+  // CHECK: CAUGHT_TRAP_LOOP_SIGILL
+  return trigger_overflow(INT_MAX, 1);
+}



More information about the llvm-commits mailing list