[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. --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -154,6 +154,14 @@ 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 @@ 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 @@ 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) // NOLINT -__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)( - void *, unsigned long, void *) = asan_thread_exit; - WIN_FORCE_LINK(__asan_dso_reg_hook) // }}}