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_allocator.h"
14 #include "asan_interceptors.h"
15 #include "asan_poisoning.h"
16 #include "asan_stack.h"
17 #include "asan_thread.h"
18 #include "asan_mapping.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 #include "sanitizer_common/sanitizer_placement_new.h"
21 #include "sanitizer_common/sanitizer_stackdepot.h"
22 #include "sanitizer_common/sanitizer_tls_get_addr.h"
23 #include "lsan/lsan_common.h"
27 // AsanThreadContext implementation.
29 void AsanThreadContext::OnCreated(void *arg
) {
30 CreateThreadContextArgs
*args
= static_cast<CreateThreadContextArgs
*>(arg
);
32 stack_id
= StackDepotPut(*args
->stack
);
33 thread
= args
->thread
;
34 thread
->set_context(this);
37 void AsanThreadContext::OnFinished() {
38 // Drop the link to the AsanThread object.
42 // MIPS requires aligned address
43 static ALIGNED(16) char thread_registry_placeholder
[sizeof(ThreadRegistry
)];
44 static ThreadRegistry
*asan_thread_registry
;
46 static BlockingMutex
mu_for_thread_context(LINKER_INITIALIZED
);
47 static LowLevelAllocator allocator_for_thread_context
;
49 static ThreadContextBase
*GetAsanThreadContext(u32 tid
) {
50 BlockingMutexLock
lock(&mu_for_thread_context
);
51 return new(allocator_for_thread_context
) AsanThreadContext(tid
);
54 ThreadRegistry
&asanThreadRegistry() {
55 static bool initialized
;
56 // Don't worry about thread_safety - this should be called when there is
59 // Never reuse ASan threads: we store pointer to AsanThreadContext
60 // in TSD and can't reliably tell when no more TSD destructors will
61 // be called. It would be wrong to reuse AsanThreadContext for another
62 // thread before all TSD destructors will be called for it.
63 asan_thread_registry
= new(thread_registry_placeholder
) ThreadRegistry(
64 GetAsanThreadContext
, kMaxNumberOfThreads
, kMaxNumberOfThreads
);
67 return *asan_thread_registry
;
70 AsanThreadContext
*GetThreadContextByTidLocked(u32 tid
) {
71 return static_cast<AsanThreadContext
*>(
72 asanThreadRegistry().GetThreadLocked(tid
));
75 // AsanThread implementation.
77 AsanThread
*AsanThread::Create(thread_callback_t start_routine
, void *arg
,
78 u32 parent_tid
, StackTrace
*stack
,
80 uptr PageSize
= GetPageSizeCached();
81 uptr size
= RoundUpTo(sizeof(AsanThread
), PageSize
);
82 AsanThread
*thread
= (AsanThread
*)MmapOrDie(size
, __func__
);
83 thread
->start_routine_
= start_routine
;
85 AsanThreadContext::CreateThreadContextArgs args
= {thread
, stack
};
86 asanThreadRegistry().CreateThread(*reinterpret_cast<uptr
*>(thread
), detached
,
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
);
103 malloc_storage().CommitBack();
104 if (common_flags()->use_sigaltstack
) UnsetAlternateSignalStack();
105 asanThreadRegistry().FinishThread(tid
);
106 FlushToDeadThreadStats(&stats_
);
107 // We also clear the shadow on thread destruction because
108 // some code may still be executing in later TSD destructors
109 // and we don't want it to have any poisoned stack.
110 ClearShadowForThreadStackAndTLS();
111 DeleteFakeStack(tid
);
112 uptr size
= RoundUpTo(sizeof(AsanThread
), GetPageSizeCached());
113 UnmapOrDie(this, size
);
117 void AsanThread::StartSwitchFiber(FakeStack
**fake_stack_save
, uptr bottom
,
119 if (atomic_load(&stack_switching_
, memory_order_relaxed
)) {
120 Report("ERROR: starting fiber switch while in fiber switch\n");
124 next_stack_bottom_
= bottom
;
125 next_stack_top_
= bottom
+ size
;
126 atomic_store(&stack_switching_
, 1, memory_order_release
);
128 FakeStack
*current_fake_stack
= fake_stack_
;
130 *fake_stack_save
= fake_stack_
;
131 fake_stack_
= nullptr;
132 SetTLSFakeStack(nullptr);
133 // if fake_stack_save is null, the fiber will die, delete the fakestack
134 if (!fake_stack_save
&& current_fake_stack
)
135 current_fake_stack
->Destroy(this->tid());
138 void AsanThread::FinishSwitchFiber(FakeStack
*fake_stack_save
,
141 if (!atomic_load(&stack_switching_
, memory_order_relaxed
)) {
142 Report("ERROR: finishing a fiber switch that has not started\n");
146 if (fake_stack_save
) {
147 SetTLSFakeStack(fake_stack_save
);
148 fake_stack_
= fake_stack_save
;
152 *bottom_old
= stack_bottom_
;
154 *size_old
= stack_top_
- stack_bottom_
;
155 stack_bottom_
= next_stack_bottom_
;
156 stack_top_
= next_stack_top_
;
157 atomic_store(&stack_switching_
, 0, memory_order_release
);
159 next_stack_bottom_
= 0;
162 inline AsanThread::StackBounds
AsanThread::GetStackBounds() const {
163 if (!atomic_load(&stack_switching_
, memory_order_acquire
)) {
164 // Make sure the stack bounds are fully initialized.
165 if (stack_bottom_
>= stack_top_
) return {0, 0};
166 return {stack_bottom_
, stack_top_
};
169 const uptr cur_stack
= (uptr
)&local
;
170 // Note: need to check next stack first, because FinishSwitchFiber
171 // may be in process of overwriting stack_top_/bottom_. But in such case
172 // we are already on the next stack.
173 if (cur_stack
>= next_stack_bottom_
&& cur_stack
< next_stack_top_
)
174 return {next_stack_bottom_
, next_stack_top_
};
175 return {stack_bottom_
, stack_top_
};
178 uptr
AsanThread::stack_top() {
179 return GetStackBounds().top
;
182 uptr
AsanThread::stack_bottom() {
183 return GetStackBounds().bottom
;
186 uptr
AsanThread::stack_size() {
187 const auto bounds
= GetStackBounds();
188 return bounds
.top
- bounds
.bottom
;
191 // We want to create the FakeStack lazyly on the first use, but not eralier
192 // than the stack size is known and the procedure has to be async-signal safe.
193 FakeStack
*AsanThread::AsyncSignalSafeLazyInitFakeStack() {
194 uptr stack_size
= this->stack_size();
195 if (stack_size
== 0) // stack_size is not yet available, don't use FakeStack.
198 // fake_stack_ has 3 states:
199 // 0 -- not initialized
200 // 1 -- being initialized
201 // ptr -- initialized
202 // This CAS checks if the state was 0 and if so changes it to state 1,
203 // if that was successful, it initializes the pointer.
204 if (atomic_compare_exchange_strong(
205 reinterpret_cast<atomic_uintptr_t
*>(&fake_stack_
), &old_val
, 1UL,
206 memory_order_relaxed
)) {
207 uptr stack_size_log
= Log2(RoundUpToPowerOfTwo(stack_size
));
208 CHECK_LE(flags()->min_uar_stack_size_log
, flags()->max_uar_stack_size_log
);
210 Min(stack_size_log
, static_cast<uptr
>(flags()->max_uar_stack_size_log
));
212 Max(stack_size_log
, static_cast<uptr
>(flags()->min_uar_stack_size_log
));
213 fake_stack_
= FakeStack::Create(stack_size_log
);
214 SetTLSFakeStack(fake_stack_
);
220 void AsanThread::Init(const InitOptions
*options
) {
221 next_stack_top_
= next_stack_bottom_
= 0;
222 atomic_store(&stack_switching_
, false, memory_order_release
);
223 CHECK_EQ(this->stack_size(), 0U);
224 SetThreadStackAndTls(options
);
225 if (stack_top_
!= stack_bottom_
) {
226 CHECK_GT(this->stack_size(), 0U);
227 CHECK(AddrIsInMem(stack_bottom_
));
228 CHECK(AddrIsInMem(stack_top_
- 1));
230 ClearShadowForThreadStackAndTLS();
231 fake_stack_
= nullptr;
232 if (__asan_option_detect_stack_use_after_return
)
233 AsyncSignalSafeLazyInitFakeStack();
235 VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
236 (void *)stack_bottom_
, (void *)stack_top_
, stack_top_
- stack_bottom_
,
240 // Fuchsia and RTEMS don't use ThreadStart.
241 // asan_fuchsia.c/asan_rtems.c define CreateMainThread and
242 // SetThreadStackAndTls.
243 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
245 thread_return_t
AsanThread::ThreadStart(
246 tid_t os_id
, atomic_uintptr_t
*signal_thread_is_registered
) {
248 asanThreadRegistry().StartThread(tid(), os_id
, ThreadType::Regular
, nullptr);
249 if (signal_thread_is_registered
)
250 atomic_store(signal_thread_is_registered
, 1, memory_order_release
);
252 if (common_flags()->use_sigaltstack
) SetAlternateSignalStack();
254 if (!start_routine_
) {
255 // start_routine_ == 0 if we're on the main thread or on one of the
256 // OS X libdispatch worker threads. But nobody is supposed to call
257 // ThreadStart() for the worker threads.
262 thread_return_t res
= start_routine_(arg_
);
264 // On POSIX systems we defer this to the TSD destructor. LSan will consider
265 // the thread's memory as non-live from the moment we call Destroy(), even
266 // though that memory might contain pointers to heap objects which will be
267 // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
268 // the TSD destructors have run might cause false positives in LSan.
269 if (!SANITIZER_POSIX
)
275 AsanThread
*CreateMainThread() {
276 AsanThread
*main_thread
= AsanThread::Create(
277 /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ 0,
278 /* stack */ nullptr, /* detached */ true);
279 SetCurrentThread(main_thread
);
280 main_thread
->ThreadStart(internal_getpid(),
281 /* signal_thread_is_registered */ nullptr);
285 // This implementation doesn't use the argument, which is just passed down
286 // from the caller of Init (which see, above). It's only there to support
287 // OS-specific implementations that need more information passed through.
288 void AsanThread::SetThreadStackAndTls(const InitOptions
*options
) {
289 DCHECK_EQ(options
, nullptr);
292 GetThreadStackAndTls(tid() == 0, &stack_bottom_
, &stack_size
, &tls_begin_
,
294 stack_top_
= stack_bottom_
+ stack_size
;
295 tls_end_
= tls_begin_
+ tls_size
;
298 if (stack_top_
!= stack_bottom_
) {
300 CHECK(AddrIsInStack((uptr
)&local
));
304 #endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
306 void AsanThread::ClearShadowForThreadStackAndTLS() {
307 if (stack_top_
!= stack_bottom_
)
308 PoisonShadow(stack_bottom_
, stack_top_
- stack_bottom_
, 0);
309 if (tls_begin_
!= tls_end_
) {
310 uptr tls_begin_aligned
= RoundDownTo(tls_begin_
, SHADOW_GRANULARITY
);
311 uptr tls_end_aligned
= RoundUpTo(tls_end_
, SHADOW_GRANULARITY
);
312 FastPoisonShadowPartialRightRedzone(tls_begin_aligned
,
313 tls_end_
- tls_begin_aligned
,
314 tls_end_aligned
- tls_end_
, 0);
318 bool AsanThread::GetStackFrameAccessByAddr(uptr addr
,
319 StackFrameAccess
*access
) {
320 if (stack_top_
== stack_bottom_
)
324 if (AddrIsInStack(addr
)) {
325 bottom
= stack_bottom();
326 } else if (has_fake_stack()) {
327 bottom
= fake_stack()->AddrIsInFakeStack(addr
);
329 access
->offset
= addr
- bottom
;
330 access
->frame_pc
= ((uptr
*)bottom
)[2];
331 access
->frame_descr
= (const char *)((uptr
*)bottom
)[1];
334 uptr aligned_addr
= RoundDownTo(addr
, SANITIZER_WORDSIZE
/ 8); // align addr.
335 uptr mem_ptr
= RoundDownTo(aligned_addr
, SHADOW_GRANULARITY
);
336 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
337 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
339 while (shadow_ptr
>= shadow_bottom
&&
340 *shadow_ptr
!= kAsanStackLeftRedzoneMagic
) {
342 mem_ptr
-= SHADOW_GRANULARITY
;
345 while (shadow_ptr
>= shadow_bottom
&&
346 *shadow_ptr
== kAsanStackLeftRedzoneMagic
) {
348 mem_ptr
-= SHADOW_GRANULARITY
;
351 if (shadow_ptr
< shadow_bottom
) {
355 uptr
* ptr
= (uptr
*)(mem_ptr
+ SHADOW_GRANULARITY
);
356 CHECK(ptr
[0] == kCurrentStackFrameMagic
);
357 access
->offset
= addr
- (uptr
)ptr
;
358 access
->frame_pc
= ptr
[2];
359 access
->frame_descr
= (const char*)ptr
[1];
363 uptr
AsanThread::GetStackVariableShadowStart(uptr addr
) {
365 if (AddrIsInStack(addr
)) {
366 bottom
= stack_bottom();
367 } else if (has_fake_stack()) {
368 bottom
= fake_stack()->AddrIsInFakeStack(addr
);
374 uptr aligned_addr
= RoundDownTo(addr
, SANITIZER_WORDSIZE
/ 8); // align addr.
375 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
376 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
378 while (shadow_ptr
>= shadow_bottom
&&
379 (*shadow_ptr
!= kAsanStackLeftRedzoneMagic
&&
380 *shadow_ptr
!= kAsanStackMidRedzoneMagic
&&
381 *shadow_ptr
!= kAsanStackRightRedzoneMagic
))
384 return (uptr
)shadow_ptr
+ 1;
387 bool AsanThread::AddrIsInStack(uptr addr
) {
388 const auto bounds
= GetStackBounds();
389 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
392 static bool ThreadStackContainsAddress(ThreadContextBase
*tctx_base
,
394 AsanThreadContext
*tctx
= static_cast<AsanThreadContext
*>(tctx_base
);
395 AsanThread
*t
= tctx
->thread
;
396 if (!t
) return false;
397 if (t
->AddrIsInStack((uptr
)addr
)) return true;
398 if (t
->has_fake_stack() && t
->fake_stack()->AddrIsInFakeStack((uptr
)addr
))
403 AsanThread
*GetCurrentThread() {
404 if (SANITIZER_RTEMS
&& !asan_inited
)
407 AsanThreadContext
*context
=
408 reinterpret_cast<AsanThreadContext
*>(AsanTSDGet());
410 if (SANITIZER_ANDROID
) {
411 // On Android, libc constructor is called _after_ asan_init, and cleans up
412 // TSD. Try to figure out if this is still the main thread by the stack
413 // address. We are not entirely sure that we have correct main thread
414 // limits, so only do this magic on Android, and only if the found thread
415 // is the main thread.
416 AsanThreadContext
*tctx
= GetThreadContextByTidLocked(0);
417 if (tctx
&& ThreadStackContainsAddress(tctx
, &context
)) {
418 SetCurrentThread(tctx
->thread
);
424 return context
->thread
;
427 void SetCurrentThread(AsanThread
*t
) {
429 VReport(2, "SetCurrentThread: %p for thread %p\n", t
->context(),
430 (void *)GetThreadSelf());
431 // Make sure we do not reset the current AsanThread.
432 CHECK_EQ(0, AsanTSDGet());
433 AsanTSDSet(t
->context());
434 CHECK_EQ(t
->context(), AsanTSDGet());
437 u32
GetCurrentTidOrInvalid() {
438 AsanThread
*t
= GetCurrentThread();
439 return t
? t
->tid() : kInvalidTid
;
442 AsanThread
*FindThreadByStackAddress(uptr addr
) {
443 asanThreadRegistry().CheckLocked();
444 AsanThreadContext
*tctx
= static_cast<AsanThreadContext
*>(
445 asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress
,
447 return tctx
? tctx
->thread
: nullptr;
450 void EnsureMainThreadIDIsCorrect() {
451 AsanThreadContext
*context
=
452 reinterpret_cast<AsanThreadContext
*>(AsanTSDGet());
453 if (context
&& (context
->tid
== 0))
454 context
->os_id
= GetTid();
457 __asan::AsanThread
*GetAsanThreadByOsIDLocked(tid_t os_id
) {
458 __asan::AsanThreadContext
*context
= static_cast<__asan::AsanThreadContext
*>(
459 __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id
));
460 if (!context
) return nullptr;
461 return context
->thread
;
463 } // namespace __asan
465 // --- Implementation of LSan-specific functions --- {{{1
467 bool GetThreadRangesLocked(tid_t os_id
, uptr
*stack_begin
, uptr
*stack_end
,
468 uptr
*tls_begin
, uptr
*tls_end
, uptr
*cache_begin
,
469 uptr
*cache_end
, DTLS
**dtls
) {
470 __asan::AsanThread
*t
= __asan::GetAsanThreadByOsIDLocked(os_id
);
471 if (!t
) return false;
472 *stack_begin
= t
->stack_bottom();
473 *stack_end
= t
->stack_top();
474 *tls_begin
= t
->tls_begin();
475 *tls_end
= t
->tls_end();
476 // ASan doesn't keep allocator caches in TLS, so these are unused.
483 void ForEachExtraStackRange(tid_t os_id
, RangeIteratorCallback callback
,
485 __asan::AsanThread
*t
= __asan::GetAsanThreadByOsIDLocked(os_id
);
486 if (t
&& t
->has_fake_stack())
487 t
->fake_stack()->ForEachFakeFrame(callback
, arg
);
490 void LockThreadRegistry() {
491 __asan::asanThreadRegistry().Lock();
494 void UnlockThreadRegistry() {
495 __asan::asanThreadRegistry().Unlock();
498 ThreadRegistry
*GetThreadRegistryLocked() {
499 __asan::asanThreadRegistry().CheckLocked();
500 return &__asan::asanThreadRegistry();
503 void EnsureMainThreadIDIsCorrect() {
504 __asan::EnsureMainThreadIDIsCorrect();
506 } // namespace __lsan
508 // ---------------------- Interface ---------------- {{{1
509 using namespace __asan
;
512 SANITIZER_INTERFACE_ATTRIBUTE
513 void __sanitizer_start_switch_fiber(void **fakestacksave
, const void *bottom
,
515 AsanThread
*t
= GetCurrentThread();
517 VReport(1, "__asan_start_switch_fiber called from unknown thread\n");
520 t
->StartSwitchFiber((FakeStack
**)fakestacksave
, (uptr
)bottom
, size
);
523 SANITIZER_INTERFACE_ATTRIBUTE
524 void __sanitizer_finish_switch_fiber(void* fakestack
,
525 const void **bottom_old
,
527 AsanThread
*t
= GetCurrentThread();
529 VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
532 t
->FinishSwitchFiber((FakeStack
*)fakestack
,