Source code

Revision control

Copy as Markdown

Other Tools

[winasan] Unpoison the stack in NtTerminateThread
In long-running builds we've seen some ASan complaints during thread creation
that we suspect are due to leftover poisoning from previous threads whose stacks
occupied that memory. This patch adds a hook that unpoisons the stack just
before the NtTerminateThread syscall.
Differential Revision: https://reviews.llvm.org/D52091
** Update for clang 9 ** : After some backouts, this patch eventually landed
upstream in a different form, as the TLS handler `asan_thread_exit`, but that
variant causes failures in our test suite, so revert the TLS handler in favor of
the interceptor approach from the first patch.
diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp
index 417892aaedd..5fe86db44f4 100644
--- a/compiler-rt/lib/asan/asan_win.cpp
+++ b/compiler-rt/lib/asan/asan_win.cpp
@@ -154,6 +154,14 @@ INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security,
thr_flags, tid);
}
+INTERCEPTOR_WINAPI(void, NtTerminateThread, void *rcx) {
+ // Unpoison the terminating thread's stack because the memory may be re-used.
+ NT_TIB *tib = (NT_TIB *)NtCurrentTeb();
+ uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit;
+ __asan_unpoison_memory_region(tib->StackLimit, stackSize);
+ return REAL(NtTerminateThread(rcx));
+}
+
// }}}
namespace __asan {
@@ -168,7 +176,9 @@ void InitializePlatformInterceptors() {
ASAN_INTERCEPT_FUNC(CreateThread);
ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
-
+ CHECK(::__interception::OverrideFunction("NtTerminateThread",
+ (uptr)WRAP(NtTerminateThread),
+ (uptr *)&REAL(NtTerminateThread)));
#ifdef _WIN64
ASAN_INTERCEPT_FUNC(__C_specific_handler);
#else
@@ -380,19 +390,6 @@ __declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
void *, unsigned long, void *) = asan_thread_init;
#endif
-static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
- if (reason == DLL_THREAD_DETACH) {
- // Unpoison the thread's stack because the memory may be re-used.
- NT_TIB *tib = (NT_TIB *)NtCurrentTeb();
- uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit;
- __asan_unpoison_memory_region(tib->StackLimit, stackSize);
- }
-}
-
-#pragma section(".CRT$XLY", long, read)
-__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
- void *, unsigned long, void *) = asan_thread_exit;
-
WIN_FORCE_LINK(__asan_dso_reg_hook)
// }}}