1 #include "dfsan_thread.h"
6 #include "sanitizer_common/sanitizer_tls_get_addr.h"
10 DFsanThread
*DFsanThread::Create(thread_callback_t start_routine
, void *arg
,
12 uptr PageSize
= GetPageSizeCached();
13 uptr size
= RoundUpTo(sizeof(DFsanThread
), PageSize
);
14 DFsanThread
*thread
= (DFsanThread
*)MmapOrDie(size
, __func__
);
15 thread
->start_routine_
= start_routine
;
17 thread
->track_origins_
= track_origins
;
18 thread
->destructor_iterations_
= GetPthreadDestructorIterations();
23 void DFsanThread::SetThreadStackAndTls() {
26 GetThreadStackAndTls(IsMainThread(), &stack_
.bottom
, &stack_size
, &tls_begin_
,
28 stack_
.top
= stack_
.bottom
+ stack_size
;
29 tls_end_
= tls_begin_
+ tls_size
;
32 CHECK(AddrIsInStack((uptr
)&local
));
35 void DFsanThread::ClearShadowForThreadStackAndTLS() {
36 dfsan_set_label(0, (void *)stack_
.bottom
, stack_
.top
- stack_
.bottom
);
37 if (tls_begin_
!= tls_end_
)
38 dfsan_set_label(0, (void *)tls_begin_
, tls_end_
- tls_begin_
);
39 DTLS
*dtls
= DTLS_Get();
41 ForEachDVT(dtls
, [](const DTLS::DTV
&dtv
, int id
) {
42 dfsan_set_label(0, (void *)(dtv
.beg
), dtv
.size
);
46 void DFsanThread::Init() {
47 SetThreadStackAndTls();
48 ClearShadowForThreadStackAndTLS();
51 void DFsanThread::TSDDtor(void *tsd
) {
52 DFsanThread
*t
= (DFsanThread
*)tsd
;
56 void DFsanThread::Destroy() {
57 malloc_storage().CommitBack();
58 // We also clear the shadow on thread destruction because
59 // some code may still be executing in later TSD destructors
60 // and we don't want it to have any poisoned stack.
61 ClearShadowForThreadStackAndTLS();
62 uptr size
= RoundUpTo(sizeof(DFsanThread
), GetPageSizeCached());
63 UnmapOrDie(this, size
);
67 thread_return_t
DFsanThread::ThreadStart() {
68 if (!start_routine_
) {
69 // start_routine_ == 0 if we're on the main thread or on one of the
70 // OS X libdispatch worker threads. But nobody is supposed to call
71 // ThreadStart() for the worker threads.
75 // The only argument is void* arg.
77 // We have never supported propagating the pointer arg as tainted,
78 // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label.
79 // Note that the bytes pointed-to (probably the much more common case)
80 // can still have taint labels attached to them.
81 dfsan_clear_thread_local_state();
83 return start_routine_(arg_
);
86 DFsanThread::StackBounds
DFsanThread::GetStackBounds() const {
87 return {stack_
.bottom
, stack_
.top
};
90 uptr
DFsanThread::stack_top() { return GetStackBounds().top
; }
92 uptr
DFsanThread::stack_bottom() { return GetStackBounds().bottom
; }
94 bool DFsanThread::AddrIsInStack(uptr addr
) {
95 const auto bounds
= GetStackBounds();
96 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
99 static pthread_key_t tsd_key
;
100 static bool tsd_key_inited
= false;
102 void DFsanTSDInit(void (*destructor
)(void *tsd
)) {
103 CHECK(!tsd_key_inited
);
104 tsd_key_inited
= true;
105 CHECK_EQ(0, pthread_key_create(&tsd_key
, destructor
));
108 static THREADLOCAL DFsanThread
*dfsan_current_thread
;
110 DFsanThread
*GetCurrentThread() { return dfsan_current_thread
; }
112 void SetCurrentThread(DFsanThread
*t
) {
113 // Make sure we do not reset the current DFsanThread.
114 CHECK_EQ(0, dfsan_current_thread
);
115 dfsan_current_thread
= t
;
116 // Make sure that DFsanTSDDtor gets called at the end.
117 CHECK(tsd_key_inited
);
118 pthread_setspecific(tsd_key
, t
);
121 void DFsanTSDDtor(void *tsd
) {
122 DFsanThread
*t
= (DFsanThread
*)tsd
;
123 if (t
->destructor_iterations_
> 1) {
124 t
->destructor_iterations_
--;
125 CHECK_EQ(0, pthread_setspecific(tsd_key
, tsd
));
128 dfsan_current_thread
= nullptr;
129 // Make sure that signal handler can not see a stale current thread pointer.
130 atomic_signal_fence(memory_order_seq_cst
);
131 DFsanThread::TSDDtor(tsd
);
134 } // namespace __dfsan