unpoison-thread-stacks_clang_21.patch (2584B)
1 [winasan] Unpoison the stack in NtTerminateThread 2 3 In long-running builds we've seen some ASan complaints during thread creation 4 that we suspect are due to leftover poisoning from previous threads whose stacks 5 occupied that memory. This patch adds a hook that unpoisons the stack just 6 before the NtTerminateThread syscall. 7 8 Differential Revision: https://reviews.llvm.org/D52091 9 10 ** Update for clang 9 ** : After some backouts, this patch eventually landed 11 upstream in a different form, as the TLS handler `asan_thread_exit`, but that 12 variant causes failures in our test suite, so revert the TLS handler in favor of 13 the interceptor approach from the first patch. 14 15 diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp 16 index 027340280e06..fbc06cf2b6c3 100644 17 --- a/compiler-rt/lib/asan/asan_win.cpp 18 +++ b/compiler-rt/lib/asan/asan_win.cpp 19 @@ -172,6 +172,14 @@ INTERCEPTOR_WINAPI(void, ExitThread, DWORD dwExitCode) { 20 REAL(ExitThread)(dwExitCode); 21 } 22 23 +INTERCEPTOR_WINAPI(void, NtTerminateThread, void *rcx) { 24 + // Unpoison the terminating thread's stack because the memory may be re-used. 25 + NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); 26 + uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit; 27 + __asan_unpoison_memory_region(tib->StackLimit, stackSize); 28 + return REAL(NtTerminateThread(rcx)); 29 +} 30 + 31 // }}} 32 33 namespace __asan { 34 @@ -189,7 +197,9 @@ void InitializePlatformInterceptors() { 35 ASAN_INTERCEPT_FUNC(CreateThread); 36 ASAN_INTERCEPT_FUNC(ExitThread); 37 ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter); 38 - 39 + CHECK(::__interception::OverrideFunction("NtTerminateThread", 40 + (uptr)WRAP(NtTerminateThread), 41 + (uptr *)&REAL(NtTerminateThread))); 42 #ifdef _WIN64 43 ASAN_INTERCEPT_FUNC(__C_specific_handler); 44 #else 45 @@ -399,19 +409,6 @@ __declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)( 46 void *, unsigned long, void *) = asan_thread_init; 47 #endif 48 49 -static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) { 50 - if (reason == DLL_THREAD_DETACH) { 51 - // Unpoison the thread's stack because the memory may be re-used. 52 - NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); 53 - uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit; 54 - __asan_unpoison_memory_region(tib->StackLimit, stackSize); 55 - } 56 -} 57 - 58 -#pragma section(".CRT$XLY", long, read) 59 -__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)( 60 - void *, unsigned long, void *) = asan_thread_exit; 61 - 62 WIN_FORCE_LINK(__asan_dso_reg_hook) 63 64 // }}}