hwasan_thread.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "hwasan_thread.h"
  2. #include "hwasan.h"
  3. #include "hwasan_interface_internal.h"
  4. #include "hwasan_mapping.h"
  5. #include "hwasan_poisoning.h"
  6. #include "hwasan_thread_list.h"
  7. #include "sanitizer_common/sanitizer_atomic.h"
  8. #include "sanitizer_common/sanitizer_file.h"
  9. #include "sanitizer_common/sanitizer_placement_new.h"
  10. #include "sanitizer_common/sanitizer_tls_get_addr.h"
  11. namespace __hwasan {
  12. static u32 RandomSeed() {
  13. u32 seed;
  14. do {
  15. if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed), sizeof(seed),
  16. /*blocking=*/false))) {
  17. seed = static_cast<u32>(
  18. (NanoTime() >> 12) ^
  19. (reinterpret_cast<uptr>(__builtin_frame_address(0)) >> 4));
  20. }
  21. } while (!seed);
  22. return seed;
  23. }
  24. void Thread::InitRandomState() {
  25. random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
  26. random_state_inited_ = true;
  27. // Push a random number of zeros onto the ring buffer so that the first stack
  28. // tag base will be random.
  29. for (tag_t i = 0, e = GenerateRandomTag(); i != e; ++i)
  30. stack_allocations_->push(0);
  31. }
  32. void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size,
  33. const InitState *state) {
  34. CHECK_EQ(0, unique_id_); // try to catch bad stack reuse
  35. CHECK_EQ(0, stack_top_);
  36. CHECK_EQ(0, stack_bottom_);
  37. static atomic_uint64_t unique_id;
  38. unique_id_ = atomic_fetch_add(&unique_id, 1, memory_order_relaxed);
  39. if (auto sz = flags()->heap_history_size)
  40. heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
  41. #if !SANITIZER_FUCHSIA
  42. // Do not initialize the stack ring buffer just yet on Fuchsia. Threads will
  43. // be initialized before we enter the thread itself, so we will instead call
  44. // this later.
  45. InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
  46. #endif
  47. InitStackAndTls(state);
  48. dtls_ = DTLS_Get();
  49. }
  50. void Thread::InitStackRingBuffer(uptr stack_buffer_start,
  51. uptr stack_buffer_size) {
  52. HwasanTSDThreadInit(); // Only needed with interceptors.
  53. uptr *ThreadLong = GetCurrentThreadLongPtr();
  54. // The following implicitly sets (this) as the current thread.
  55. stack_allocations_ = new (ThreadLong)
  56. StackAllocationsRingBuffer((void *)stack_buffer_start, stack_buffer_size);
  57. // Check that it worked.
  58. CHECK_EQ(GetCurrentThread(), this);
  59. // ScopedTaggingDisable needs GetCurrentThread to be set up.
  60. ScopedTaggingDisabler disabler;
  61. if (stack_bottom_) {
  62. int local;
  63. CHECK(AddrIsInStack((uptr)&local));
  64. CHECK(MemIsApp(stack_bottom_));
  65. CHECK(MemIsApp(stack_top_ - 1));
  66. }
  67. if (flags()->verbose_threads) {
  68. if (IsMainThread()) {
  69. Printf("sizeof(Thread): %zd sizeof(HeapRB): %zd sizeof(StackRB): %zd\n",
  70. sizeof(Thread), heap_allocations_->SizeInBytes(),
  71. stack_allocations_->size() * sizeof(uptr));
  72. }
  73. Print("Creating : ");
  74. }
  75. }
  76. void Thread::ClearShadowForThreadStackAndTLS() {
  77. if (stack_top_ != stack_bottom_)
  78. TagMemory(stack_bottom_, stack_top_ - stack_bottom_, 0);
  79. if (tls_begin_ != tls_end_)
  80. TagMemory(tls_begin_, tls_end_ - tls_begin_, 0);
  81. }
  82. void Thread::Destroy() {
  83. if (flags()->verbose_threads)
  84. Print("Destroying: ");
  85. AllocatorSwallowThreadLocalCache(allocator_cache());
  86. ClearShadowForThreadStackAndTLS();
  87. if (heap_allocations_)
  88. heap_allocations_->Delete();
  89. DTLS_Destroy();
  90. // Unregister this as the current thread.
  91. // Instrumented code can not run on this thread from this point onwards, but
  92. // malloc/free can still be served. Glibc may call free() very late, after all
  93. // TSD destructors are done.
  94. CHECK_EQ(GetCurrentThread(), this);
  95. *GetCurrentThreadLongPtr() = 0;
  96. }
  97. void Thread::Print(const char *Prefix) {
  98. Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix, unique_id_,
  99. (void *)this, stack_bottom(), stack_top(),
  100. stack_top() - stack_bottom(), tls_begin(), tls_end());
  101. }
  102. static u32 xorshift(u32 state) {
  103. state ^= state << 13;
  104. state ^= state >> 17;
  105. state ^= state << 5;
  106. return state;
  107. }
  108. // Generate a (pseudo-)random non-zero tag.
  109. tag_t Thread::GenerateRandomTag(uptr num_bits) {
  110. DCHECK_GT(num_bits, 0);
  111. if (tagging_disabled_)
  112. return 0;
  113. tag_t tag;
  114. const uptr tag_mask = (1ULL << num_bits) - 1;
  115. do {
  116. if (flags()->random_tags) {
  117. if (!random_buffer_) {
  118. EnsureRandomStateInited();
  119. random_buffer_ = random_state_ = xorshift(random_state_);
  120. }
  121. CHECK(random_buffer_);
  122. tag = random_buffer_ & tag_mask;
  123. random_buffer_ >>= num_bits;
  124. } else {
  125. EnsureRandomStateInited();
  126. random_state_ += 1;
  127. tag = random_state_ & tag_mask;
  128. }
  129. } while (!tag);
  130. return tag;
  131. }
  132. } // namespace __hwasan
  133. // --- Implementation of LSan-specific functions --- {{{1
  134. namespace __lsan {
  135. static __hwasan::HwasanThreadList *GetHwasanThreadListLocked() {
  136. auto &tl = __hwasan::hwasanThreadList();
  137. tl.CheckLocked();
  138. return &tl;
  139. }
  140. static __hwasan::Thread *GetThreadByOsIDLocked(tid_t os_id) {
  141. return GetHwasanThreadListLocked()->FindThreadLocked(
  142. [os_id](__hwasan::Thread *t) { return t->os_id() == os_id; });
  143. }
  144. void LockThreadRegistry() { __hwasan::hwasanThreadList().Lock(); }
  145. void UnlockThreadRegistry() { __hwasan::hwasanThreadList().Unlock(); }
  146. void EnsureMainThreadIDIsCorrect() {
  147. auto *t = __hwasan::GetCurrentThread();
  148. if (t && (t->IsMainThread()))
  149. t->set_os_id(GetTid());
  150. }
  151. bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
  152. uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
  153. uptr *cache_end, DTLS **dtls) {
  154. auto *t = GetThreadByOsIDLocked(os_id);
  155. if (!t)
  156. return false;
  157. *stack_begin = t->stack_bottom();
  158. *stack_end = t->stack_top();
  159. *tls_begin = t->tls_begin();
  160. *tls_end = t->tls_end();
  161. // Fixme: is this correct for HWASan.
  162. *cache_begin = 0;
  163. *cache_end = 0;
  164. *dtls = t->dtls();
  165. return true;
  166. }
  167. void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
  168. void GetThreadExtraStackRangesLocked(tid_t os_id,
  169. InternalMmapVector<Range> *ranges) {}
  170. void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {}
  171. void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {}
  172. void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {}
  173. } // namespace __lsan