1 #include "dfsan_thread.h"
6 #include "sanitizer_common/sanitizer_tls_get_addr.h"
8 using namespace __dfsan
;
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() {
24 GetThreadStackAndTls(IsMainThread(), &stack_
.bottom
, &stack_
.top
, &tls_begin_
,
27 CHECK(AddrIsInStack((uptr
)&local
));
30 void DFsanThread::ClearShadowForThreadStackAndTLS() {
31 dfsan_set_label(0, (void *)stack_
.bottom
, stack_
.top
- stack_
.bottom
);
32 if (tls_begin_
!= tls_end_
)
33 dfsan_set_label(0, (void *)tls_begin_
, tls_end_
- tls_begin_
);
34 DTLS
*dtls
= DTLS_Get();
36 ForEachDVT(dtls
, [](const DTLS::DTV
&dtv
, int id
) {
37 dfsan_set_label(0, (void *)(dtv
.beg
), dtv
.size
);
41 void DFsanThread::Init() {
42 SetThreadStackAndTls();
43 ClearShadowForThreadStackAndTLS();
46 void DFsanThread::TSDDtor(void *tsd
) {
47 DFsanThread
*t
= (DFsanThread
*)tsd
;
51 void DFsanThread::Destroy() {
52 malloc_storage().CommitBack();
53 // We also clear the shadow on thread destruction because
54 // some code may still be executing in later TSD destructors
55 // and we don't want it to have any poisoned stack.
56 ClearShadowForThreadStackAndTLS();
57 uptr size
= RoundUpTo(sizeof(DFsanThread
), GetPageSizeCached());
58 UnmapOrDie(this, size
);
62 thread_return_t
DFsanThread::ThreadStart() {
63 if (!start_routine_
) {
64 // start_routine_ == 0 if we're on the main thread or on one of the
65 // OS X libdispatch worker threads. But nobody is supposed to call
66 // ThreadStart() for the worker threads.
70 // The only argument is void* arg.
72 // We have never supported propagating the pointer arg as tainted,
73 // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label.
74 // Note that the bytes pointed-to (probably the much more common case)
75 // can still have taint labels attached to them.
76 dfsan_clear_thread_local_state();
78 return start_routine_(arg_
);
81 DFsanThread::StackBounds
DFsanThread::GetStackBounds() const {
82 return {stack_
.bottom
, stack_
.top
};
85 uptr
DFsanThread::stack_top() { return GetStackBounds().top
; }
87 uptr
DFsanThread::stack_bottom() { return GetStackBounds().bottom
; }
89 bool DFsanThread::AddrIsInStack(uptr addr
) {
90 const auto bounds
= GetStackBounds();
91 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
94 static pthread_key_t tsd_key
;
95 static bool tsd_key_inited
= false;
97 void __dfsan::DFsanTSDInit(void (*destructor
)(void *tsd
)) {
98 CHECK(!tsd_key_inited
);
99 tsd_key_inited
= true;
100 CHECK_EQ(0, pthread_key_create(&tsd_key
, destructor
));
103 static THREADLOCAL DFsanThread
*dfsan_current_thread
;
105 DFsanThread
*__dfsan::GetCurrentThread() { return dfsan_current_thread
; }
107 void __dfsan::SetCurrentThread(DFsanThread
*t
) {
108 // Make sure we do not reset the current DFsanThread.
109 CHECK_EQ(0, dfsan_current_thread
);
110 dfsan_current_thread
= t
;
111 // Make sure that DFsanTSDDtor gets called at the end.
112 CHECK(tsd_key_inited
);
113 pthread_setspecific(tsd_key
, t
);
116 void __dfsan::DFsanTSDDtor(void *tsd
) {
117 DFsanThread
*t
= (DFsanThread
*)tsd
;
118 if (t
->destructor_iterations_
> 1) {
119 t
->destructor_iterations_
--;
120 CHECK_EQ(0, pthread_setspecific(tsd_key
, tsd
));
123 dfsan_current_thread
= nullptr;
124 // Make sure that signal handler can not see a stale current thread pointer.
125 atomic_signal_fence(memory_order_seq_cst
);
126 DFsanThread::TSDDtor(tsd
);