dfsan_thread.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "dfsan_thread.h"
  2. #include <pthread.h>
  3. #include "dfsan.h"
  4. #include "sanitizer_common/sanitizer_tls_get_addr.h"
  5. namespace __dfsan {
  6. DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg,
  7. bool track_origins) {
  8. uptr PageSize = GetPageSizeCached();
  9. uptr size = RoundUpTo(sizeof(DFsanThread), PageSize);
  10. DFsanThread *thread = (DFsanThread *)MmapOrDie(size, __func__);
  11. thread->start_routine_ = start_routine;
  12. thread->arg_ = arg;
  13. thread->track_origins_ = track_origins;
  14. thread->destructor_iterations_ = GetPthreadDestructorIterations();
  15. return thread;
  16. }
  17. void DFsanThread::SetThreadStackAndTls() {
  18. uptr tls_size = 0;
  19. uptr stack_size = 0;
  20. GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
  21. &tls_size);
  22. stack_.top = stack_.bottom + stack_size;
  23. tls_end_ = tls_begin_ + tls_size;
  24. int local;
  25. CHECK(AddrIsInStack((uptr)&local));
  26. }
  27. void DFsanThread::ClearShadowForThreadStackAndTLS() {
  28. dfsan_set_label(0, (void *)stack_.bottom, stack_.top - stack_.bottom);
  29. if (tls_begin_ != tls_end_)
  30. dfsan_set_label(0, (void *)tls_begin_, tls_end_ - tls_begin_);
  31. DTLS *dtls = DTLS_Get();
  32. CHECK_NE(dtls, 0);
  33. ForEachDVT(dtls, [](const DTLS::DTV &dtv, int id) {
  34. dfsan_set_label(0, (void *)(dtv.beg), dtv.size);
  35. });
  36. }
  37. void DFsanThread::Init() {
  38. SetThreadStackAndTls();
  39. ClearShadowForThreadStackAndTLS();
  40. }
  41. void DFsanThread::TSDDtor(void *tsd) {
  42. DFsanThread *t = (DFsanThread *)tsd;
  43. t->Destroy();
  44. }
  45. void DFsanThread::Destroy() {
  46. malloc_storage().CommitBack();
  47. // We also clear the shadow on thread destruction because
  48. // some code may still be executing in later TSD destructors
  49. // and we don't want it to have any poisoned stack.
  50. ClearShadowForThreadStackAndTLS();
  51. uptr size = RoundUpTo(sizeof(DFsanThread), GetPageSizeCached());
  52. UnmapOrDie(this, size);
  53. DTLS_Destroy();
  54. }
  55. thread_return_t DFsanThread::ThreadStart() {
  56. if (!start_routine_) {
  57. // start_routine_ == 0 if we're on the main thread or on one of the
  58. // OS X libdispatch worker threads. But nobody is supposed to call
  59. // ThreadStart() for the worker threads.
  60. return 0;
  61. }
  62. // The only argument is void* arg.
  63. //
  64. // We have never supported propagating the pointer arg as tainted,
  65. // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label.
  66. // Note that the bytes pointed-to (probably the much more common case)
  67. // can still have taint labels attached to them.
  68. dfsan_clear_thread_local_state();
  69. return start_routine_(arg_);
  70. }
  71. DFsanThread::StackBounds DFsanThread::GetStackBounds() const {
  72. return {stack_.bottom, stack_.top};
  73. }
  74. uptr DFsanThread::stack_top() { return GetStackBounds().top; }
  75. uptr DFsanThread::stack_bottom() { return GetStackBounds().bottom; }
  76. bool DFsanThread::AddrIsInStack(uptr addr) {
  77. const auto bounds = GetStackBounds();
  78. return addr >= bounds.bottom && addr < bounds.top;
  79. }
  80. static pthread_key_t tsd_key;
  81. static bool tsd_key_inited = false;
  82. void DFsanTSDInit(void (*destructor)(void *tsd)) {
  83. CHECK(!tsd_key_inited);
  84. tsd_key_inited = true;
  85. CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
  86. }
  87. static THREADLOCAL DFsanThread *dfsan_current_thread;
  88. DFsanThread *GetCurrentThread() { return dfsan_current_thread; }
  89. void SetCurrentThread(DFsanThread *t) {
  90. // Make sure we do not reset the current DFsanThread.
  91. CHECK_EQ(0, dfsan_current_thread);
  92. dfsan_current_thread = t;
  93. // Make sure that DFsanTSDDtor gets called at the end.
  94. CHECK(tsd_key_inited);
  95. pthread_setspecific(tsd_key, t);
  96. }
  97. void DFsanTSDDtor(void *tsd) {
  98. DFsanThread *t = (DFsanThread *)tsd;
  99. if (t->destructor_iterations_ > 1) {
  100. t->destructor_iterations_--;
  101. CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
  102. return;
  103. }
  104. dfsan_current_thread = nullptr;
  105. // Make sure that signal handler can not see a stale current thread pointer.
  106. atomic_signal_fence(memory_order_seq_cst);
  107. DFsanThread::TSDDtor(tsd);
  108. }
  109. } // namespace __dfsan