[compiler-rt] 8a570a8 - [hwasan] Support malloc in atfork.
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 17 15:30:07 PDT 2021
Author: Evgenii Stepanov
Date: 2021-08-17T15:29:49-07:00
New Revision: 8a570a873b25af4c718a16caa214b4f7bc14e6d6
URL: https://github.com/llvm/llvm-project/commit/8a570a873b25af4c718a16caa214b4f7bc14e6d6
DIFF: https://github.com/llvm/llvm-project/commit/8a570a873b25af4c718a16caa214b4f7bc14e6d6.diff
LOG: [hwasan] Support malloc in atfork.
Before this change we were locking the StackDepot in the fork()
interceptor. This results in a deadlock when allocator functions are
used in a pthread_atfork() callback.
Instead, set up a pthread_atfork() callback at init that locks/unlocks
both StackDepot and the allocator. Since our callback is set up very
early, the pre-fork callback is executed late, and both post-fork ones
are executed early, which works perfect for us.
Differential Revision: https://reviews.llvm.org/D108063
Added:
compiler-rt/test/hwasan/TestCases/Linux/atfork.cpp
Modified:
compiler-rt/lib/hwasan/hwasan.cpp
compiler-rt/lib/hwasan/hwasan.h
compiler-rt/lib/hwasan/hwasan_allocator.cpp
compiler-rt/lib/hwasan/hwasan_fuchsia.cpp
compiler-rt/lib/hwasan/hwasan_interceptors.cpp
compiler-rt/lib/hwasan/hwasan_linux.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp
index e687f56b63f59..465419022123f 100644
--- a/compiler-rt/lib/hwasan/hwasan.cpp
+++ b/compiler-rt/lib/hwasan/hwasan.cpp
@@ -360,6 +360,7 @@ __attribute__((constructor(0))) void __hwasan_init() {
HwasanTSDThreadInit();
HwasanAllocatorInit();
+ HwasanInstallAtForkHandler();
#if HWASAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h
index 7338b696ad341..1ea310a7051f0 100644
--- a/compiler-rt/lib/hwasan/hwasan.h
+++ b/compiler-rt/lib/hwasan/hwasan.h
@@ -107,6 +107,8 @@ void InitThreads();
void InitializeInterceptors();
void HwasanAllocatorInit();
+void HwasanAllocatorLock();
+void HwasanAllocatorUnlock();
void *hwasan_malloc(uptr size, StackTrace *stack);
void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
@@ -140,6 +142,8 @@ void HwasanAtExit();
void HwasanOnDeadlySignal(int signo, void *info, void *context);
+void HwasanInstallAtForkHandler();
+
void UpdateMemoryUsage();
void AppendToErrorMessageBuffer(const char *buffer);
diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
index 7d8b9f9212a99..482eaa2e0ff76 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
@@ -107,6 +107,10 @@ void HwasanAllocatorInit() {
tail_magic[i] = GetCurrentThread()->GenerateRandomTag();
}
+void HwasanAllocatorLock() { allocator.ForceLock(); }
+
+void HwasanAllocatorUnlock() { allocator.ForceUnlock(); }
+
void AllocatorSwallowThreadLocalCache(AllocatorCache *cache) {
allocator.SwallowCache(cache);
}
diff --git a/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp b/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp
index e299a7e862eba..f51e148197b91 100644
--- a/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp
@@ -180,6 +180,8 @@ void HwasanTSDThreadInit() {}
// function is unneeded.
void InstallAtExitHandler() {}
+void HwasanInstallAtForkHandler() {}
+
// TODO(fxbug.dev/81499): Once we finalize the tagged pointer ABI in zircon, we should come back
// here and implement the appropriate check that TBI is enabled.
void InitializeOsSupport() {}
diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
index 68f8adec0776a..3a1dbf288a595 100644
--- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
@@ -125,22 +125,6 @@ INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
-static void BeforeFork() {
- StackDepotLockAll();
-}
-
-static void AfterFork() {
- StackDepotUnlockAll();
-}
-
-INTERCEPTOR(int, fork, void) {
- ENSURE_HWASAN_INITED();
- BeforeFork();
- int pid = REAL(fork)();
- AfterFork();
- return pid;
-}
-
namespace __hwasan {
int OnExit() {
@@ -156,8 +140,6 @@ void InitializeInterceptors() {
static int inited = 0;
CHECK_EQ(inited, 0);
- INTERCEPT_FUNCTION(fork);
-
#if HWASAN_WITH_INTERCEPTORS
#if defined(__linux__)
INTERCEPT_FUNCTION(vfork);
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp
index aa62a39ac6e9f..1319db6e2d1b0 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp
@@ -38,6 +38,7 @@
# include "hwasan_thread_list.h"
# include "sanitizer_common/sanitizer_common.h"
# include "sanitizer_common/sanitizer_procmaps.h"
+# include "sanitizer_common/sanitizer_stackdepot.h"
// Configurations of HWASAN_WITH_INTERCEPTORS and SANITIZER_ANDROID.
//
@@ -428,6 +429,18 @@ uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
return AddTagToPointer(p, tag);
}
+void HwasanInstallAtForkHandler() {
+ auto before = []() {
+ HwasanAllocatorLock();
+ StackDepotLockAll();
+ };
+ auto after = []() {
+ StackDepotUnlockAll();
+ HwasanAllocatorUnlock();
+ };
+ pthread_atfork(before, after, after);
+}
+
} // namespace __hwasan
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/compiler-rt/test/hwasan/TestCases/Linux/atfork.cpp b/compiler-rt/test/hwasan/TestCases/Linux/atfork.cpp
new file mode 100644
index 0000000000000..b9f805f327d64
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/Linux/atfork.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_hwasan -O0 %s -o %t && %run %t 2>&1
+
+// REQUIRES: aarch64-target-arch || x86_64-target-arch
+// REQUIRES: pointer-tagging
+
+#include <assert.h>
+#include <pthread.h>
+#include <sanitizer/hwasan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+void *volatile sink;
+
+int main(int argc, char **argv) {
+ pthread_atfork(nullptr, nullptr, []() {
+ alarm(5);
+ sink = malloc(10);
+ });
+ int pid = fork();
+ if (pid) {
+ int wstatus;
+ do {
+ waitpid(pid, &wstatus, 0);
+ } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
+ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) {
+ fprintf(stderr, "abnormal exit\n");
+ return 1;
+ }
+ }
+ return 0;
+}
More information about the llvm-commits
mailing list