3 #include "hwasan_mapping.h"
4 #include "hwasan_thread.h"
5 #include "hwasan_poisoning.h"
6 #include "hwasan_interface_internal.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"
15 static u32
RandomSeed() {
18 if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed
), sizeof(seed
),
19 /*blocking=*/false))) {
20 seed
= static_cast<u32
>(
22 (reinterpret_cast<uptr
>(__builtin_frame_address(0)) >> 4));
28 void Thread::InitRandomState() {
29 random_state_
= flags()->random_tags
? RandomSeed() : unique_id_
;
31 // Push a random number of zeros onto the ring buffer so that the first stack
32 // tag base will be random.
33 for (tag_t i
= 0, e
= GenerateRandomTag(); i
!= e
; ++i
)
34 stack_allocations_
->push(0);
37 void Thread::Init(uptr stack_buffer_start
, uptr stack_buffer_size
) {
38 CHECK_EQ(0, unique_id_
); // try to catch bad stack reuse
39 CHECK_EQ(0, stack_top_
);
40 CHECK_EQ(0, stack_bottom_
);
43 unique_id_
= unique_id
++;
44 if (auto sz
= flags()->heap_history_size
)
45 heap_allocations_
= HeapAllocationsRingBuffer::New(sz
);
47 HwasanTSDThreadInit(); // Only needed with interceptors.
48 uptr
*ThreadLong
= GetCurrentThreadLongPtr();
49 // The following implicitly sets (this) as the current thread.
50 stack_allocations_
= new (ThreadLong
)
51 StackAllocationsRingBuffer((void *)stack_buffer_start
, stack_buffer_size
);
52 // Check that it worked.
53 CHECK_EQ(GetCurrentThread(), this);
55 // ScopedTaggingDisable needs GetCurrentThread to be set up.
56 ScopedTaggingDisabler disabler
;
60 GetThreadStackAndTls(IsMainThread(), &stack_bottom_
, &stack_size
, &tls_begin_
,
62 stack_top_
= stack_bottom_
+ stack_size
;
63 tls_end_
= tls_begin_
+ tls_size
;
67 CHECK(AddrIsInStack((uptr
)&local
));
68 CHECK(MemIsApp(stack_bottom_
));
69 CHECK(MemIsApp(stack_top_
- 1));
72 if (flags()->verbose_threads
) {
74 Printf("sizeof(Thread): %zd sizeof(HeapRB): %zd sizeof(StackRB): %zd\n",
75 sizeof(Thread
), heap_allocations_
->SizeInBytes(),
76 stack_allocations_
->size() * sizeof(uptr
));
82 void Thread::ClearShadowForThreadStackAndTLS() {
83 if (stack_top_
!= stack_bottom_
)
84 TagMemory(stack_bottom_
, stack_top_
- stack_bottom_
, 0);
85 if (tls_begin_
!= tls_end_
)
86 TagMemory(tls_begin_
, tls_end_
- tls_begin_
, 0);
89 void Thread::Destroy() {
90 if (flags()->verbose_threads
)
91 Print("Destroying: ");
92 AllocatorSwallowThreadLocalCache(allocator_cache());
93 ClearShadowForThreadStackAndTLS();
94 if (heap_allocations_
)
95 heap_allocations_
->Delete();
97 // Unregister this as the current thread.
98 // Instrumented code can not run on this thread from this point onwards, but
99 // malloc/free can still be served. Glibc may call free() very late, after all
100 // TSD destructors are done.
101 CHECK_EQ(GetCurrentThread(), this);
102 *GetCurrentThreadLongPtr() = 0;
105 void Thread::Print(const char *Prefix
) {
106 Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix
,
107 unique_id_
, this, stack_bottom(), stack_top(),
108 stack_top() - stack_bottom(),
109 tls_begin(), tls_end());
112 static u32
xorshift(u32 state
) {
113 state
^= state
<< 13;
114 state
^= state
>> 17;
119 // Generate a (pseudo-)random non-zero tag.
120 tag_t
Thread::GenerateRandomTag(uptr num_bits
) {
121 DCHECK_GT(num_bits
, 0);
122 if (tagging_disabled_
) return 0;
124 const uptr tag_mask
= (1ULL << num_bits
) - 1;
126 if (flags()->random_tags
) {
128 random_buffer_
= random_state_
= xorshift(random_state_
);
129 CHECK(random_buffer_
);
130 tag
= random_buffer_
& tag_mask
;
131 random_buffer_
>>= num_bits
;
134 tag
= random_state_
& tag_mask
;
140 } // namespace __hwasan