[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