1 //===-- asan_thread.cpp ---------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // Thread-related code.
12 //===----------------------------------------------------------------------===//
13 #include "asan_thread.h"
15 #include "asan_allocator.h"
16 #include "asan_interceptors.h"
17 #include "asan_mapping.h"
18 #include "asan_poisoning.h"
19 #include "asan_stack.h"
20 #include "lsan/lsan_common.h"
21 #include "sanitizer_common/sanitizer_common.h"
22 #include "sanitizer_common/sanitizer_placement_new.h"
23 #include "sanitizer_common/sanitizer_stackdepot.h"
24 #include "sanitizer_common/sanitizer_tls_get_addr.h"
28 // AsanThreadContext implementation.
30 void AsanThreadContext::OnCreated(void *arg
) {
31 CreateThreadContextArgs
*args
= static_cast<CreateThreadContextArgs
*>(arg
);
33 stack_id
= StackDepotPut(*args
->stack
);
34 thread
= args
->thread
;
35 thread
->set_context(this);
38 void AsanThreadContext::OnFinished() {
39 // Drop the link to the AsanThread object.
43 // MIPS requires aligned address
44 static ALIGNED(16) char thread_registry_placeholder
[sizeof(ThreadRegistry
)];
45 static ThreadRegistry
*asan_thread_registry
;
47 static Mutex mu_for_thread_context
;
48 static LowLevelAllocator allocator_for_thread_context
;
50 static ThreadContextBase
*GetAsanThreadContext(u32 tid
) {
51 Lock
lock(&mu_for_thread_context
);
52 return new(allocator_for_thread_context
) AsanThreadContext(tid
);
55 ThreadRegistry
&asanThreadRegistry() {
56 static bool initialized
;
57 // Don't worry about thread_safety - this should be called when there is
60 // Never reuse ASan threads: we store pointer to AsanThreadContext
61 // in TSD and can't reliably tell when no more TSD destructors will
62 // be called. It would be wrong to reuse AsanThreadContext for another
63 // thread before all TSD destructors will be called for it.
64 asan_thread_registry
=
65 new (thread_registry_placeholder
) ThreadRegistry(GetAsanThreadContext
);
68 return *asan_thread_registry
;
71 AsanThreadContext
*GetThreadContextByTidLocked(u32 tid
) {
72 return static_cast<AsanThreadContext
*>(
73 asanThreadRegistry().GetThreadLocked(tid
));
76 // AsanThread implementation.
78 AsanThread
*AsanThread::Create(thread_callback_t start_routine
, void *arg
,
79 u32 parent_tid
, StackTrace
*stack
,
81 uptr PageSize
= GetPageSizeCached();
82 uptr size
= RoundUpTo(sizeof(AsanThread
), PageSize
);
83 AsanThread
*thread
= (AsanThread
*)MmapOrDie(size
, __func__
);
84 thread
->start_routine_
= start_routine
;
86 AsanThreadContext::CreateThreadContextArgs args
= {thread
, stack
};
87 asanThreadRegistry().CreateThread(0, detached
, parent_tid
, &args
);
92 void AsanThread::TSDDtor(void *tsd
) {
93 AsanThreadContext
*context
= (AsanThreadContext
*)tsd
;
94 VReport(1, "T%d TSDDtor\n", context
->tid
);
96 context
->thread
->Destroy();
99 void AsanThread::Destroy() {
100 int tid
= this->tid();
101 VReport(1, "T%d exited\n", tid
);
104 (asanThreadRegistry().FinishThread(tid
) == ThreadStatusRunning
);
106 if (AsanThread
*thread
= GetCurrentThread())
107 CHECK_EQ(this, thread
);
108 malloc_storage().CommitBack();
109 if (common_flags()->use_sigaltstack
)
110 UnsetAlternateSignalStack();
111 FlushToDeadThreadStats(&stats_
);
112 // We also clear the shadow on thread destruction because
113 // some code may still be executing in later TSD destructors
114 // and we don't want it to have any poisoned stack.
115 ClearShadowForThreadStackAndTLS();
116 DeleteFakeStack(tid
);
118 CHECK_NE(this, GetCurrentThread());
120 uptr size
= RoundUpTo(sizeof(AsanThread
), GetPageSizeCached());
121 UnmapOrDie(this, size
);
126 void AsanThread::StartSwitchFiber(FakeStack
**fake_stack_save
, uptr bottom
,
128 if (atomic_load(&stack_switching_
, memory_order_relaxed
)) {
129 Report("ERROR: starting fiber switch while in fiber switch\n");
133 next_stack_bottom_
= bottom
;
134 next_stack_top_
= bottom
+ size
;
135 atomic_store(&stack_switching_
, 1, memory_order_release
);
137 FakeStack
*current_fake_stack
= fake_stack_
;
139 *fake_stack_save
= fake_stack_
;
140 fake_stack_
= nullptr;
141 SetTLSFakeStack(nullptr);
142 // if fake_stack_save is null, the fiber will die, delete the fakestack
143 if (!fake_stack_save
&& current_fake_stack
)
144 current_fake_stack
->Destroy(this->tid());
147 void AsanThread::FinishSwitchFiber(FakeStack
*fake_stack_save
,
150 if (!atomic_load(&stack_switching_
, memory_order_relaxed
)) {
151 Report("ERROR: finishing a fiber switch that has not started\n");
155 if (fake_stack_save
) {
156 SetTLSFakeStack(fake_stack_save
);
157 fake_stack_
= fake_stack_save
;
161 *bottom_old
= stack_bottom_
;
163 *size_old
= stack_top_
- stack_bottom_
;
164 stack_bottom_
= next_stack_bottom_
;
165 stack_top_
= next_stack_top_
;
166 atomic_store(&stack_switching_
, 0, memory_order_release
);
168 next_stack_bottom_
= 0;
171 inline AsanThread::StackBounds
AsanThread::GetStackBounds() const {
172 if (!atomic_load(&stack_switching_
, memory_order_acquire
)) {
173 // Make sure the stack bounds are fully initialized.
174 if (stack_bottom_
>= stack_top_
) return {0, 0};
175 return {stack_bottom_
, stack_top_
};
178 const uptr cur_stack
= (uptr
)&local
;
179 // Note: need to check next stack first, because FinishSwitchFiber
180 // may be in process of overwriting stack_top_/bottom_. But in such case
181 // we are already on the next stack.
182 if (cur_stack
>= next_stack_bottom_
&& cur_stack
< next_stack_top_
)
183 return {next_stack_bottom_
, next_stack_top_
};
184 return {stack_bottom_
, stack_top_
};
187 uptr
AsanThread::stack_top() {
188 return GetStackBounds().top
;
191 uptr
AsanThread::stack_bottom() {
192 return GetStackBounds().bottom
;
195 uptr
AsanThread::stack_size() {
196 const auto bounds
= GetStackBounds();
197 return bounds
.top
- bounds
.bottom
;
200 // We want to create the FakeStack lazily on the first use, but not earlier
201 // than the stack size is known and the procedure has to be async-signal safe.
202 FakeStack
*AsanThread::AsyncSignalSafeLazyInitFakeStack() {
203 uptr stack_size
= this->stack_size();
204 if (stack_size
== 0) // stack_size is not yet available, don't use FakeStack.
207 // fake_stack_ has 3 states:
208 // 0 -- not initialized
209 // 1 -- being initialized
210 // ptr -- initialized
211 // This CAS checks if the state was 0 and if so changes it to state 1,
212 // if that was successful, it initializes the pointer.
213 if (atomic_compare_exchange_strong(
214 reinterpret_cast<atomic_uintptr_t
*>(&fake_stack_
), &old_val
, 1UL,
215 memory_order_relaxed
)) {
216 uptr stack_size_log
= Log2(RoundUpToPowerOfTwo(stack_size
));
217 CHECK_LE(flags()->min_uar_stack_size_log
, flags()->max_uar_stack_size_log
);
219 Min(stack_size_log
, static_cast<uptr
>(flags()->max_uar_stack_size_log
));
221 Max(stack_size_log
, static_cast<uptr
>(flags()->min_uar_stack_size_log
));
222 fake_stack_
= FakeStack::Create(stack_size_log
);
223 DCHECK_EQ(GetCurrentThread(), this);
224 SetTLSFakeStack(fake_stack_
);
230 void AsanThread::Init(const InitOptions
*options
) {
231 DCHECK_NE(tid(), kInvalidTid
);
232 next_stack_top_
= next_stack_bottom_
= 0;
233 atomic_store(&stack_switching_
, false, memory_order_release
);
234 CHECK_EQ(this->stack_size(), 0U);
235 SetThreadStackAndTls(options
);
236 if (stack_top_
!= stack_bottom_
) {
237 CHECK_GT(this->stack_size(), 0U);
238 CHECK(AddrIsInMem(stack_bottom_
));
239 CHECK(AddrIsInMem(stack_top_
- 1));
241 ClearShadowForThreadStackAndTLS();
242 fake_stack_
= nullptr;
243 if (__asan_option_detect_stack_use_after_return
&&
244 tid() == GetCurrentTidOrInvalid()) {
245 // AsyncSignalSafeLazyInitFakeStack makes use of threadlocals and must be
246 // called from the context of the thread it is initializing, not its parent.
247 // Most platforms call AsanThread::Init on the newly-spawned thread, but
248 // Fuchsia calls this function from the parent thread. To support that
249 // approach, we avoid calling AsyncSignalSafeLazyInitFakeStack here; it will
250 // be called by the new thread when it first attempts to access the fake
252 AsyncSignalSafeLazyInitFakeStack();
255 VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
256 (void *)stack_bottom_
, (void *)stack_top_
, stack_top_
- stack_bottom_
,
260 // Fuchsia doesn't use ThreadStart.
261 // asan_fuchsia.c definies CreateMainThread and SetThreadStackAndTls.
262 #if !SANITIZER_FUCHSIA
264 thread_return_t
AsanThread::ThreadStart(tid_t os_id
) {
266 asanThreadRegistry().StartThread(tid(), os_id
, ThreadType::Regular
, nullptr);
268 if (common_flags()->use_sigaltstack
) SetAlternateSignalStack();
270 if (!start_routine_
) {
271 // start_routine_ == 0 if we're on the main thread or on one of the
272 // OS X libdispatch worker threads. But nobody is supposed to call
273 // ThreadStart() for the worker threads.
278 thread_return_t res
= start_routine_(arg_
);
280 // On POSIX systems we defer this to the TSD destructor. LSan will consider
281 // the thread's memory as non-live from the moment we call Destroy(), even
282 // though that memory might contain pointers to heap objects which will be
283 // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
284 // the TSD destructors have run might cause false positives in LSan.
285 if (!SANITIZER_POSIX
)
291 AsanThread
*CreateMainThread() {
292 AsanThread
*main_thread
= AsanThread::Create(
293 /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid
,
294 /* stack */ nullptr, /* detached */ true);
295 SetCurrentThread(main_thread
);
296 main_thread
->ThreadStart(internal_getpid());
300 // This implementation doesn't use the argument, which is just passed down
301 // from the caller of Init (which see, above). It's only there to support
302 // OS-specific implementations that need more information passed through.
303 void AsanThread::SetThreadStackAndTls(const InitOptions
*options
) {
304 DCHECK_EQ(options
, nullptr);
307 GetThreadStackAndTls(tid() == kMainTid
, &stack_bottom_
, &stack_size
,
308 &tls_begin_
, &tls_size
);
309 stack_top_
= RoundDownTo(stack_bottom_
+ stack_size
, ASAN_SHADOW_GRANULARITY
);
310 stack_bottom_
= RoundDownTo(stack_bottom_
, ASAN_SHADOW_GRANULARITY
);
311 tls_end_
= tls_begin_
+ tls_size
;
314 if (stack_top_
!= stack_bottom_
) {
316 CHECK(AddrIsInStack((uptr
)&local
));
320 #endif // !SANITIZER_FUCHSIA
322 void AsanThread::ClearShadowForThreadStackAndTLS() {
323 if (stack_top_
!= stack_bottom_
)
324 PoisonShadow(stack_bottom_
, stack_top_
- stack_bottom_
, 0);
325 if (tls_begin_
!= tls_end_
) {
326 uptr tls_begin_aligned
= RoundDownTo(tls_begin_
, ASAN_SHADOW_GRANULARITY
);
327 uptr tls_end_aligned
= RoundUpTo(tls_end_
, ASAN_SHADOW_GRANULARITY
);
328 FastPoisonShadow(tls_begin_aligned
, tls_end_aligned
- tls_begin_aligned
, 0);
332 bool AsanThread::GetStackFrameAccessByAddr(uptr addr
,
333 StackFrameAccess
*access
) {
334 if (stack_top_
== stack_bottom_
)
338 if (AddrIsInStack(addr
)) {
339 bottom
= stack_bottom();
340 } else if (FakeStack
*fake_stack
= get_fake_stack()) {
341 bottom
= fake_stack
->AddrIsInFakeStack(addr
);
343 access
->offset
= addr
- bottom
;
344 access
->frame_pc
= ((uptr
*)bottom
)[2];
345 access
->frame_descr
= (const char *)((uptr
*)bottom
)[1];
348 uptr aligned_addr
= RoundDownTo(addr
, SANITIZER_WORDSIZE
/ 8); // align addr.
349 uptr mem_ptr
= RoundDownTo(aligned_addr
, ASAN_SHADOW_GRANULARITY
);
350 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
351 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
353 while (shadow_ptr
>= shadow_bottom
&&
354 *shadow_ptr
!= kAsanStackLeftRedzoneMagic
) {
356 mem_ptr
-= ASAN_SHADOW_GRANULARITY
;
359 while (shadow_ptr
>= shadow_bottom
&&
360 *shadow_ptr
== kAsanStackLeftRedzoneMagic
) {
362 mem_ptr
-= ASAN_SHADOW_GRANULARITY
;
365 if (shadow_ptr
< shadow_bottom
) {
369 uptr
*ptr
= (uptr
*)(mem_ptr
+ ASAN_SHADOW_GRANULARITY
);
370 CHECK(ptr
[0] == kCurrentStackFrameMagic
);
371 access
->offset
= addr
- (uptr
)ptr
;
372 access
->frame_pc
= ptr
[2];
373 access
->frame_descr
= (const char*)ptr
[1];
377 uptr
AsanThread::GetStackVariableShadowStart(uptr addr
) {
379 if (AddrIsInStack(addr
)) {
380 bottom
= stack_bottom();
381 } else if (FakeStack
*fake_stack
= get_fake_stack()) {
382 bottom
= fake_stack
->AddrIsInFakeStack(addr
);
390 uptr aligned_addr
= RoundDownTo(addr
, SANITIZER_WORDSIZE
/ 8); // align addr.
391 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
392 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
394 while (shadow_ptr
>= shadow_bottom
&&
395 (*shadow_ptr
!= kAsanStackLeftRedzoneMagic
&&
396 *shadow_ptr
!= kAsanStackMidRedzoneMagic
&&
397 *shadow_ptr
!= kAsanStackRightRedzoneMagic
))
400 return (uptr
)shadow_ptr
+ 1;
403 bool AsanThread::AddrIsInStack(uptr addr
) {
404 const auto bounds
= GetStackBounds();
405 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
408 static bool ThreadStackContainsAddress(ThreadContextBase
*tctx_base
,
410 AsanThreadContext
*tctx
= static_cast<AsanThreadContext
*>(tctx_base
);
411 AsanThread
*t
= tctx
->thread
;
414 if (t
->AddrIsInStack((uptr
)addr
))
416 FakeStack
*fake_stack
= t
->get_fake_stack();
419 return fake_stack
->AddrIsInFakeStack((uptr
)addr
);
422 AsanThread
*GetCurrentThread() {
423 AsanThreadContext
*context
=
424 reinterpret_cast<AsanThreadContext
*>(AsanTSDGet());
426 if (SANITIZER_ANDROID
) {
427 // On Android, libc constructor is called _after_ asan_init, and cleans up
428 // TSD. Try to figure out if this is still the main thread by the stack
429 // address. We are not entirely sure that we have correct main thread
430 // limits, so only do this magic on Android, and only if the found thread
431 // is the main thread.
432 AsanThreadContext
*tctx
= GetThreadContextByTidLocked(kMainTid
);
433 if (tctx
&& ThreadStackContainsAddress(tctx
, &context
)) {
434 SetCurrentThread(tctx
->thread
);
440 return context
->thread
;
443 void SetCurrentThread(AsanThread
*t
) {
445 VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t
->context(),
446 (void *)GetThreadSelf());
447 // Make sure we do not reset the current AsanThread.
448 CHECK_EQ(0, AsanTSDGet());
449 AsanTSDSet(t
->context());
450 CHECK_EQ(t
->context(), AsanTSDGet());
453 u32
GetCurrentTidOrInvalid() {
454 AsanThread
*t
= GetCurrentThread();
455 return t
? t
->tid() : kInvalidTid
;
458 AsanThread
*FindThreadByStackAddress(uptr addr
) {
459 asanThreadRegistry().CheckLocked();
460 AsanThreadContext
*tctx
= static_cast<AsanThreadContext
*>(
461 asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress
,
463 return tctx
? tctx
->thread
: nullptr;
466 void EnsureMainThreadIDIsCorrect() {
467 AsanThreadContext
*context
=
468 reinterpret_cast<AsanThreadContext
*>(AsanTSDGet());
469 if (context
&& (context
->tid
== kMainTid
))
470 context
->os_id
= GetTid();
473 __asan::AsanThread
*GetAsanThreadByOsIDLocked(tid_t os_id
) {
474 __asan::AsanThreadContext
*context
= static_cast<__asan::AsanThreadContext
*>(
475 __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id
));
476 if (!context
) return nullptr;
477 return context
->thread
;
479 } // namespace __asan
481 // --- Implementation of LSan-specific functions --- {{{1
483 void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); }
485 void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); }
487 static ThreadRegistry
*GetAsanThreadRegistryLocked() {
488 __asan::asanThreadRegistry().CheckLocked();
489 return &__asan::asanThreadRegistry();
492 void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); }
494 bool GetThreadRangesLocked(tid_t os_id
, uptr
*stack_begin
, uptr
*stack_end
,
495 uptr
*tls_begin
, uptr
*tls_end
, uptr
*cache_begin
,
496 uptr
*cache_end
, DTLS
**dtls
) {
497 __asan::AsanThread
*t
= __asan::GetAsanThreadByOsIDLocked(os_id
);
498 if (!t
) return false;
499 *stack_begin
= t
->stack_bottom();
500 *stack_end
= t
->stack_top();
501 *tls_begin
= t
->tls_begin();
502 *tls_end
= t
->tls_end();
503 // ASan doesn't keep allocator caches in TLS, so these are unused.
510 void GetAllThreadAllocatorCachesLocked(InternalMmapVector
<uptr
> *caches
) {}
512 void GetThreadExtraStackRangesLocked(tid_t os_id
,
513 InternalMmapVector
<Range
> *ranges
) {
514 __asan::AsanThread
*t
= __asan::GetAsanThreadByOsIDLocked(os_id
);
517 __asan::FakeStack
*fake_stack
= t
->get_fake_stack();
521 fake_stack
->ForEachFakeFrame(
522 [](uptr begin
, uptr end
, void *arg
) {
523 reinterpret_cast<InternalMmapVector
<Range
> *>(arg
)->push_back(
529 void GetThreadExtraStackRangesLocked(InternalMmapVector
<Range
> *ranges
) {
530 GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
531 [](ThreadContextBase
*tctx
, void *arg
) {
532 GetThreadExtraStackRangesLocked(
533 tctx
->os_id
, reinterpret_cast<InternalMmapVector
<Range
> *>(arg
));
538 void GetAdditionalThreadContextPtrsLocked(InternalMmapVector
<uptr
> *ptrs
) {
539 GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
540 [](ThreadContextBase
*tctx
, void *ptrs
) {
541 // Look for the arg pointer of threads that have been created or are
542 // running. This is necessary to prevent false positive leaks due to the
543 // AsanThread holding the only live reference to a heap object. This
544 // can happen because the `pthread_create()` interceptor doesn't wait
545 // for the child thread to start before returning and thus loosing the
546 // the only live reference to the heap object on the stack.
548 __asan::AsanThreadContext
*atctx
=
549 static_cast<__asan::AsanThreadContext
*>(tctx
);
551 // Note ThreadStatusRunning is required because there is a small window
552 // where the thread status switches to `ThreadStatusRunning` but the
553 // `arg` pointer still isn't on the stack yet.
554 if (atctx
->status
!= ThreadStatusCreated
&&
555 atctx
->status
!= ThreadStatusRunning
)
558 uptr thread_arg
= reinterpret_cast<uptr
>(atctx
->thread
->get_arg());
562 auto ptrsVec
= reinterpret_cast<InternalMmapVector
<uptr
> *>(ptrs
);
563 ptrsVec
->push_back(thread_arg
);
568 void GetRunningThreadsLocked(InternalMmapVector
<tid_t
> *threads
) {
569 GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
570 [](ThreadContextBase
*tctx
, void *threads
) {
571 if (tctx
->status
== ThreadStatusRunning
)
572 reinterpret_cast<InternalMmapVector
<tid_t
> *>(threads
)->push_back(
578 void FinishThreadLocked(u32 tid
) {
579 GetAsanThreadRegistryLocked()->FinishThread(tid
);
582 } // namespace __lsan
584 // ---------------------- Interface ---------------- {{{1
585 using namespace __asan
;
588 SANITIZER_INTERFACE_ATTRIBUTE
589 void __sanitizer_start_switch_fiber(void **fakestacksave
, const void *bottom
,
591 AsanThread
*t
= GetCurrentThread();
593 VReport(1, "__asan_start_switch_fiber called from unknown thread\n");
596 t
->StartSwitchFiber((FakeStack
**)fakestacksave
, (uptr
)bottom
, size
);
599 SANITIZER_INTERFACE_ATTRIBUTE
600 void __sanitizer_finish_switch_fiber(void* fakestack
,
601 const void **bottom_old
,
603 AsanThread
*t
= GetCurrentThread();
605 VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
608 t
->FinishSwitchFiber((FakeStack
*)fakestack
,