brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · 55d3891 Raw
128 lines · cpp
1#include "dfsan_thread.h"2 3#include <pthread.h>4 5#include "dfsan.h"6#include "sanitizer_common/sanitizer_tls_get_addr.h"7 8using namespace __dfsan;9 10DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg,11                                 bool track_origins) {12  uptr PageSize = GetPageSizeCached();13  uptr size = RoundUpTo(sizeof(DFsanThread), PageSize);14  DFsanThread *thread = (DFsanThread *)MmapOrDie(size, __func__);15  thread->start_routine_ = start_routine;16  thread->arg_ = arg;17  thread->track_origins_ = track_origins;18  thread->destructor_iterations_ = GetPthreadDestructorIterations();19 20  return thread;21}22 23void DFsanThread::SetThreadStackAndTls() {24  GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_.top, &tls_begin_,25                       &tls_end_);26  int local;27  CHECK(AddrIsInStack((uptr)&local));28}29 30void 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();35  CHECK_NE(dtls, 0);36  ForEachDVT(dtls, [](const DTLS::DTV &dtv, int id) {37    dfsan_set_label(0, (void *)(dtv.beg), dtv.size);38  });39}40 41void DFsanThread::Init() {42  SetThreadStackAndTls();43  ClearShadowForThreadStackAndTLS();44}45 46void DFsanThread::TSDDtor(void *tsd) {47  DFsanThread *t = (DFsanThread *)tsd;48  t->Destroy();49}50 51void DFsanThread::Destroy() {52  malloc_storage().CommitBack();53  // We also clear the shadow on thread destruction because54  // some code may still be executing in later TSD destructors55  // and we don't want it to have any poisoned stack.56  ClearShadowForThreadStackAndTLS();57  uptr size = RoundUpTo(sizeof(DFsanThread), GetPageSizeCached());58  UnmapOrDie(this, size);59  DTLS_Destroy();60}61 62thread_return_t DFsanThread::ThreadStart() {63  if (!start_routine_) {64    // start_routine_ == 0 if we're on the main thread or on one of the65    // OS X libdispatch worker threads. But nobody is supposed to call66    // ThreadStart() for the worker threads.67    return 0;68  }69 70  // The only argument is void* arg.71  //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();77 78  return start_routine_(arg_);79}80 81DFsanThread::StackBounds DFsanThread::GetStackBounds() const {82  return {stack_.bottom, stack_.top};83}84 85uptr DFsanThread::stack_top() { return GetStackBounds().top; }86 87uptr DFsanThread::stack_bottom() { return GetStackBounds().bottom; }88 89bool DFsanThread::AddrIsInStack(uptr addr) {90  const auto bounds = GetStackBounds();91  return addr >= bounds.bottom && addr < bounds.top;92}93 94static pthread_key_t tsd_key;95static bool tsd_key_inited = false;96 97void __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));101}102 103static THREADLOCAL DFsanThread *dfsan_current_thread;104 105DFsanThread *__dfsan::GetCurrentThread() { return dfsan_current_thread; }106 107void __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);114}115 116void __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));121    return;122  }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);127}128