msan_thread.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "msan.h"
  2. #include "msan_thread.h"
  3. #include "msan_interface_internal.h"
  4. #include "sanitizer_common/sanitizer_tls_get_addr.h"
  5. namespace __msan {
  6. MsanThread *MsanThread::Create(thread_callback_t start_routine,
  7. void *arg) {
  8. uptr PageSize = GetPageSizeCached();
  9. uptr size = RoundUpTo(sizeof(MsanThread), PageSize);
  10. MsanThread *thread = (MsanThread*)MmapOrDie(size, __func__);
  11. thread->start_routine_ = start_routine;
  12. thread->arg_ = arg;
  13. thread->destructor_iterations_ = GetPthreadDestructorIterations();
  14. return thread;
  15. }
  16. void MsanThread::SetThreadStackAndTls() {
  17. uptr tls_size = 0;
  18. uptr stack_size = 0;
  19. GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
  20. &tls_size);
  21. stack_.top = stack_.bottom + stack_size;
  22. tls_end_ = tls_begin_ + tls_size;
  23. int local;
  24. CHECK(AddrIsInStack((uptr)&local));
  25. }
  26. void MsanThread::ClearShadowForThreadStackAndTLS() {
  27. __msan_unpoison((void *)stack_.bottom, stack_.top - stack_.bottom);
  28. if (tls_begin_ != tls_end_)
  29. __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
  30. DTLS *dtls = DTLS_Get();
  31. CHECK_NE(dtls, 0);
  32. ForEachDVT(dtls, [](const DTLS::DTV &dtv, int id) {
  33. __msan_unpoison((void *)(dtv.beg), dtv.size);
  34. });
  35. }
  36. void MsanThread::Init() {
  37. SetThreadStackAndTls();
  38. CHECK(MEM_IS_APP(stack_.bottom));
  39. CHECK(MEM_IS_APP(stack_.top - 1));
  40. ClearShadowForThreadStackAndTLS();
  41. malloc_storage().Init();
  42. }
  43. void MsanThread::TSDDtor(void *tsd) {
  44. MsanThread *t = (MsanThread*)tsd;
  45. t->Destroy();
  46. }
  47. void MsanThread::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(MsanThread), GetPageSizeCached());
  54. UnmapOrDie(this, size);
  55. DTLS_Destroy();
  56. }
  57. thread_return_t MsanThread::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. thread_return_t res = start_routine_(arg_);
  65. return res;
  66. }
  67. MsanThread::StackBounds MsanThread::GetStackBounds() const {
  68. if (!stack_switching_)
  69. return {stack_.bottom, stack_.top};
  70. const uptr cur_stack = GET_CURRENT_FRAME();
  71. // Note: need to check next stack first, because FinishSwitchFiber
  72. // may be in process of overwriting stack_.top/bottom_. But in such case
  73. // we are already on the next stack.
  74. if (cur_stack >= next_stack_.bottom && cur_stack < next_stack_.top)
  75. return {next_stack_.bottom, next_stack_.top};
  76. return {stack_.bottom, stack_.top};
  77. }
  78. uptr MsanThread::stack_top() { return GetStackBounds().top; }
  79. uptr MsanThread::stack_bottom() { return GetStackBounds().bottom; }
  80. bool MsanThread::AddrIsInStack(uptr addr) {
  81. const auto bounds = GetStackBounds();
  82. return addr >= bounds.bottom && addr < bounds.top;
  83. }
  84. void MsanThread::StartSwitchFiber(uptr bottom, uptr size) {
  85. CHECK(!stack_switching_);
  86. next_stack_.bottom = bottom;
  87. next_stack_.top = bottom + size;
  88. stack_switching_ = true;
  89. }
  90. void MsanThread::FinishSwitchFiber(uptr *bottom_old, uptr *size_old) {
  91. CHECK(stack_switching_);
  92. if (bottom_old)
  93. *bottom_old = stack_.bottom;
  94. if (size_old)
  95. *size_old = stack_.top - stack_.bottom;
  96. stack_.bottom = next_stack_.bottom;
  97. stack_.top = next_stack_.top;
  98. stack_switching_ = false;
  99. next_stack_.top = 0;
  100. next_stack_.bottom = 0;
  101. }
  102. } // namespace __msan