aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2023-12-13 13:09:36 -0800
committerGitHub <noreply@github.com>2023-12-13 13:09:36 -0800
commit14d7e0bb0f75066da5d2eff718b6d59215a02077 (patch)
tree93d45d260321f36988906f414731275955c0ec7f
parente8f43883a073f4ef71e7f724143e068099649952 (diff)
downloadllvm-14d7e0bb0f75066da5d2eff718b6d59215a02077.zip
llvm-14d7e0bb0f75066da5d2eff718b6d59215a02077.tar.gz
llvm-14d7e0bb0f75066da5d2eff718b6d59215a02077.tar.bz2
[lsan] Install `pthread_atfork` (#75281)
This prevents deadlocks in forked process on essencial runtime components.
-rw-r--r--compiler-rt/lib/lsan/lsan.cpp1
-rw-r--r--compiler-rt/lib/lsan/lsan.h1
-rw-r--r--compiler-rt/lib/lsan/lsan_common.cpp3
-rw-r--r--compiler-rt/lib/lsan/lsan_common.h4
-rw-r--r--compiler-rt/lib/lsan/lsan_fuchsia.cpp1
-rw-r--r--compiler-rt/lib/lsan/lsan_posix.cpp18
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.c2
7 files changed, 29 insertions, 1 deletions
diff --git a/compiler-rt/lib/lsan/lsan.cpp b/compiler-rt/lib/lsan/lsan.cpp
index 6b22360..7a27b60 100644
--- a/compiler-rt/lib/lsan/lsan.cpp
+++ b/compiler-rt/lib/lsan/lsan.cpp
@@ -101,6 +101,7 @@ extern "C" void __lsan_init() {
InstallDeadlySignalHandlers(LsanOnDeadlySignal);
InitializeMainThread();
InstallAtExitCheckLeaks();
+ InstallAtForkHandler();
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
diff --git a/compiler-rt/lib/lsan/lsan.h b/compiler-rt/lib/lsan/lsan.h
index 757edec..0074ad5 100644
--- a/compiler-rt/lib/lsan/lsan.h
+++ b/compiler-rt/lib/lsan/lsan.h
@@ -40,6 +40,7 @@ void InitializeInterceptors();
void ReplaceSystemMalloc();
void LsanOnDeadlySignal(int signo, void *siginfo, void *context);
void InstallAtExitCheckLeaks();
+void InstallAtForkHandler();
#define ENSURE_LSAN_INITED \
do { \
diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
index 8b1af5b..e24839c 100644
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -42,6 +42,9 @@ namespace __lsan {
// also to protect the global list of root regions.
static Mutex global_mutex;
+void LockGlobal() SANITIZER_ACQUIRE(global_mutex) { global_mutex.Lock(); }
+void UnlockGlobal() SANITIZER_RELEASE(global_mutex) { global_mutex.Unlock(); }
+
Flags lsan_flags;
void DisableCounterUnderflow() {
diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h
index d3e7683..c598b62 100644
--- a/compiler-rt/lib/lsan/lsan_common.h
+++ b/compiler-rt/lib/lsan/lsan_common.h
@@ -120,6 +120,10 @@ void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads);
void LockAllocator();
void UnlockAllocator();
+// Lock/unlock global mutext.
+void LockGlobal();
+void UnlockGlobal();
+
// Returns the address range occupied by the global allocator object.
void GetAllocatorGlobalRange(uptr *begin, uptr *end);
// If p points into a chunk that has been allocated to the user, returns its
diff --git a/compiler-rt/lib/lsan/lsan_fuchsia.cpp b/compiler-rt/lib/lsan/lsan_fuchsia.cpp
index 4edac97..ba59bc9 100644
--- a/compiler-rt/lib/lsan/lsan_fuchsia.cpp
+++ b/compiler-rt/lib/lsan/lsan_fuchsia.cpp
@@ -80,6 +80,7 @@ void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
// So this doesn't install any atexit hook like on other platforms.
void InstallAtExitCheckLeaks() {}
+void InstallAtForkHandler() {}
// ASan defines this to check its `halt_on_error` flag.
bool UseExitcodeOnLeak() { return true; }
diff --git a/compiler-rt/lib/lsan/lsan_posix.cpp b/compiler-rt/lib/lsan/lsan_posix.cpp
index 732b8af..3677f01 100644
--- a/compiler-rt/lib/lsan/lsan_posix.cpp
+++ b/compiler-rt/lib/lsan/lsan_posix.cpp
@@ -14,6 +14,8 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_POSIX
+# include <pthread.h>
+
# include "lsan.h"
# include "lsan_allocator.h"
# include "lsan_thread.h"
@@ -98,6 +100,22 @@ void InstallAtExitCheckLeaks() {
Atexit(DoLeakCheck);
}
+void InstallAtForkHandler() {
+ auto before = []() {
+ LockGlobal();
+ LockThreads();
+ LockAllocator();
+ StackDepotLockAll();
+ };
+ auto after = []() {
+ StackDepotUnlockAll();
+ UnlockAllocator();
+ UnlockThreads();
+ UnlockGlobal();
+ };
+ pthread_atfork(before, after, after);
+}
+
} // namespace __lsan
#endif // SANITIZER_POSIX
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.c b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.c
index eaa1a04..7592269 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.c
@@ -1,6 +1,6 @@
// RUN: %clang -O0 %s -o %t && %env_tool_opts=die_after_fork=0 %run %t
-// UNSUPPORTED: asan, lsan, hwasan
+// UNSUPPORTED: asan, hwasan
// The test uses pthread barriers which are not available on Darwin.
// UNSUPPORTED: darwin