diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h --- a/compiler-rt/lib/hwasan/hwasan.h +++ b/compiler-rt/lib/hwasan/hwasan.h @@ -107,6 +107,8 @@ 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 HwasanOnDeadlySignal(int signo, void *info, void *context); +void HwasanInstallAtForkHandler(); + void UpdateMemoryUsage(); void AppendToErrorMessageBuffer(const char *buffer); diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp --- a/compiler-rt/lib/hwasan/hwasan.cpp +++ b/compiler-rt/lib/hwasan/hwasan.cpp @@ -360,6 +360,7 @@ HwasanTSDThreadInit(); HwasanAllocatorInit(); + HwasanInstallAtForkHandler(); #if HWASAN_CONTAINS_UBSAN __ubsan::InitAsPlugin(); diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -107,6 +107,10 @@ 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 --- a/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp +++ b/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp @@ -180,6 +180,8 @@ // 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 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -125,22 +125,6 @@ #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 @@ 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 --- 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 @@ 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 --- /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 +#include +#include +#include +#include +#include +#include +#include + +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; +}