[compiler-rt] [compiler-rt][common] Only unmap stacks the runtime has actually mapped (PR #179000)
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Sun May 10 18:51:51 PDT 2026
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/179000
>From cbc6633acd6b1c23b953e16c4ab011e2f2421d6b Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Fri, 30 Jan 2026 16:01:44 -0800
Subject: [PATCH 1/4] [compiler-rt][common] Don't unmap stacks not mapped by
the runtime
When the sanitizer hasn't mapped the alternate signal stack, but the
host program has (like LLVM), the runtime still tries to unilaterally
unmap the alternate stack. Instead, the runtime should just check if
it's actually mmaped the alternate stack, and only unmap it if it has.
---
.../lib/sanitizer_common/sanitizer_posix_libcdep.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 8e5e87938c372..8cb040b4d1f9e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -49,6 +49,8 @@ namespace __sanitizer {
[[maybe_unused]] static atomic_uint8_t signal_handler_is_from_sanitizer[64];
+static THREADLOCAL void* allocated_alt_stack_base = nullptr;
+
u32 GetUid() {
return getuid();
}
@@ -201,6 +203,7 @@ void SetAlternateSignalStack() {
altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__);
altstack.ss_flags = 0;
CHECK_EQ(0, sigaltstack(&altstack, nullptr));
+ allocated_alt_stack_base = altstack.ss_sp;
}
void UnsetAlternateSignalStack() {
@@ -209,7 +212,11 @@ void UnsetAlternateSignalStack() {
altstack.ss_flags = SS_DISABLE;
altstack.ss_size = GetAltStackSize(); // Some sane value required on Darwin.
CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
- UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+ if (allocated_alt_stack_base != 0 &&
+ allocated_alt_stack_base == oldstack.ss_sp) {
+ UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+ allocated_alt_stack_base = nullptr;
+ }
}
bool IsSignalHandlerFromSanitizer(int signum) {
>From 0b7de5837b1db8a3cf26d046ddb4d9562e12776b Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Fri, 20 Feb 2026 16:00:36 -0800
Subject: [PATCH 2/4] Use AsanThread to store pointer
---
compiler-rt/lib/asan/asan_thread.cpp | 4 ++--
compiler-rt/lib/asan/asan_thread.h | 1 +
.../lib/sanitizer_common/sanitizer_common.h | 4 ++--
.../lib/sanitizer_common/sanitizer_fuchsia.cpp | 4 ++--
.../sanitizer_common/sanitizer_posix_libcdep.cpp | 14 +++++---------
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp | 5 +++--
6 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp
index 32ab723e89001..ec96ec9b8082b 100644
--- a/compiler-rt/lib/asan/asan_thread.cpp
+++ b/compiler-rt/lib/asan/asan_thread.cpp
@@ -132,7 +132,7 @@ void AsanThread::Destroy() {
CHECK_EQ(this, thread);
malloc_storage().CommitBack();
if (common_flags()->use_sigaltstack)
- UnsetAlternateSignalStack();
+ UnsetAlternateSignalStack(altstack_base_);
FlushToDeadThreadStats(&stats_);
// We also clear the shadow on thread destruction because
// some code may still be executing in later TSD destructors
@@ -288,7 +288,7 @@ void AsanThread::ThreadStart(ThreadID os_id) {
asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr);
if (common_flags()->use_sigaltstack)
- SetAlternateSignalStack();
+ altstack_base_ = SetAlternateSignalStack();
}
AsanThread *CreateMainThread() {
diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h
index e9ca6b6a59016..b356998459d9d 100644
--- a/compiler-rt/lib/asan/asan_thread.h
+++ b/compiler-rt/lib/asan/asan_thread.h
@@ -190,6 +190,7 @@ class AsanThread {
AsanStats stats_;
bool unwinding_;
uptr extra_spill_area_;
+ void *altstack_base_ = nullptr;
char start_data_[];
};
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 564ae301475a9..d029930967755 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -387,8 +387,8 @@ void ReportDeadlySignal(const SignalContext &sig, u32 tid,
const void *unwind_context);
// Alternative signal stack (POSIX-only).
-void SetAlternateSignalStack();
-void UnsetAlternateSignalStack();
+void *SetAlternateSignalStack();
+void UnsetAlternateSignalStack(void *altstack_base);
bool IsSignalHandlerFromSanitizer(int signum);
bool SetSignalHandlerFromSanitizer(int signum, bool new_state);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
index 3c61b60802996..4dc31f4e51efa 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -93,8 +93,8 @@ void CheckMPROTECT() {}
void PlatformPrepareForSandboxing(void *args) {}
void DisableCoreDumperIfNecessary() {}
void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
-void SetAlternateSignalStack() {}
-void UnsetAlternateSignalStack() {}
+void* SetAlternateSignalStack() { return nullptr; }
+void UnsetAlternateSignalStack(void* altstack_base) {}
bool SignalContext::IsStackOverflow() const { return false; }
void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 8cb040b4d1f9e..a3f2ca61b6f95 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -49,8 +49,6 @@ namespace __sanitizer {
[[maybe_unused]] static atomic_uint8_t signal_handler_is_from_sanitizer[64];
-static THREADLOCAL void* allocated_alt_stack_base = nullptr;
-
u32 GetUid() {
return getuid();
}
@@ -190,12 +188,12 @@ static uptr GetAltStackSize() {
return SIGSTKSZ * 4;
}
-void SetAlternateSignalStack() {
+void* SetAlternateSignalStack() {
stack_t altstack, oldstack;
CHECK_EQ(0, sigaltstack(nullptr, &oldstack));
// If the alternate stack is already in place, do nothing.
// Android always sets an alternate stack, but it's too small for us.
- if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
+ if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return nullptr;
// TODO(glider): the mapped stack should have the MAP_STACK flag in the
// future. It is not required by man 2 sigaltstack now (they're using
// malloc()).
@@ -203,19 +201,17 @@ void SetAlternateSignalStack() {
altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__);
altstack.ss_flags = 0;
CHECK_EQ(0, sigaltstack(&altstack, nullptr));
- allocated_alt_stack_base = altstack.ss_sp;
+ return altstack.ss_sp;
}
-void UnsetAlternateSignalStack() {
+void UnsetAlternateSignalStack(void* altstack_base) {
stack_t altstack, oldstack;
altstack.ss_sp = nullptr;
altstack.ss_flags = SS_DISABLE;
altstack.ss_size = GetAltStackSize(); // Some sane value required on Darwin.
CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
- if (allocated_alt_stack_base != 0 &&
- allocated_alt_stack_base == oldstack.ss_sp) {
+ if (altstack_base && altstack_base == oldstack.ss_sp) {
UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
- allocated_alt_stack_base = nullptr;
}
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index ed4f60deeffc8..70f4a936c1329 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -913,11 +913,12 @@ void ReportFile::Write(const char *buffer, uptr length) {
}
}
-void SetAlternateSignalStack() {
+void* SetAlternateSignalStack() {
// FIXME: Decide what to do on Windows.
+ return nullptr;
}
-void UnsetAlternateSignalStack() {
+void UnsetAlternateSignalStack(void* altstack_base) {
// FIXME: Decide what to do on Windows.
}
>From 344812801f2e3f941a140ff9c8eabebf7bb7843d Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Mon, 23 Feb 2026 13:47:36 -0800
Subject: [PATCH 3/4] Add test case
---
.../TestCases/Posix/multiple_sigaltstack.cpp | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
diff --git a/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp b/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
new file mode 100644
index 0000000000000..b70e6ff485a98
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan %s -o %t && %env_asan_opts=use_sigaltstack=1 %run %t
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+char global_alt_stack[4096 * 4];
+
+int main() {
+ stack_t altstack;
+ altstack.ss_sp = global_alt_stack;
+ altstack.ss_size = sizeof(global_alt_stack);
+ altstack.ss_flags = 0;
+ if (sigaltstack(&altstack, nullptr) != 0) {
+ perror("sigaltstack");
+ exit(1);
+ }
+
+ // UnsetAlternateSignalStack will get called when the thread exists. If we
+ // don't *only* unmap a signal stack the runtime owns, we'll get a fault on
+ // the munmap operation, since that memory isn't mmaped.
+ return 0;
+}
>From 19231dbc09bd32ace3a71d57ee2725d878969ae7 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 10 May 2026 18:51:41 -0700
Subject: [PATCH 4/4] Reorder includes
---
compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp b/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
index b70e6ff485a98..a7cf4b3a43b91 100644
--- a/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
+++ b/compiler-rt/test/asan/TestCases/Posix/multiple_sigaltstack.cpp
@@ -1,9 +1,9 @@
// RUN: %clangxx_asan %s -o %t && %env_asan_opts=use_sigaltstack=1 %run %t
+#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <pthread.h>
char global_alt_stack[4096 * 4];
More information about the llvm-commits
mailing list