[tsan] Don't symbolize stack traces if dl_iterate_phdr is not ready (#143199)

When a CHECK() fails during TSan initialization, it may segfault (e.g., https://github.com/google/sanitizers/issues/837#issuecomment-2939267531). This is because a failed CHECK() will attempt to print a symbolized stack trace, which requires dl_iterate_phdr, but the interceptor may not yet be set up.

This patch fixes the issue by not symbolizing the stack trace if the dl_iterate_phdr interceptor is not ready.
This commit is contained in:
Thurston Dang
2025-06-09 09:29:16 -07:00
committed by GitHub
parent 4ed0ff8756
commit a178c06add
4 changed files with 22 additions and 1 deletions

View File

@@ -3085,6 +3085,10 @@ void InitializeInterceptors() {
#if !SANITIZER_ANDROID
TSAN_INTERCEPT(dl_iterate_phdr);
#endif
// Symbolization indirectly calls dl_iterate_phdr
ready_to_symbolize = true;
TSAN_MAYBE_INTERCEPT_ON_EXIT;
TSAN_INTERCEPT(__cxa_atexit);
TSAN_INTERCEPT(_exit);

View File

@@ -679,6 +679,12 @@ void CheckUnwind() {
bool is_initialized;
// Symbolization indirectly calls dl_iterate_phdr. If a CHECK() fails early on
// (prior to the dl_iterate_phdr interceptor setup), resulting in an attempted
// symbolization, it will segfault.
// dl_iterate_phdr is not intercepted for Android.
bool ready_to_symbolize = SANITIZER_ANDROID;
void Initialize(ThreadState *thr) {
// Thread safe because done before all threads exist.
if (is_initialized)

View File

@@ -54,6 +54,8 @@
namespace __tsan {
extern bool ready_to_symbolize;
#if !SANITIZER_GO
struct MapUnmapCallback;
# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \

View File

@@ -846,7 +846,16 @@ ALWAYS_INLINE USED void PrintCurrentStack(uptr pc, bool fast) {
ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
}
if (ready_to_symbolize) {
PrintStack(SymbolizeStack(*ptrace));
} else {
Printf(
"WARNING: PrintCurrentStack() has been called too early, before "
"symbolization is possible. Printing unsymbolized stack trace:\n");
for (unsigned int i = 0; i < ptrace->size; i++)
Printf(" #%u: 0x%zx\n", i, ptrace->trace[i]);
}
#endif
}