dfsan_thread.cpp 4.4 KB

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