msan_thread.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. }
  42. void MsanThread::TSDDtor(void *tsd) {
  43. MsanThread *t = (MsanThread*)tsd;
  44. t->Destroy();
  45. }
  46. void MsanThread::Destroy() {
  47. malloc_storage().CommitBack();
  48. // We also clear the shadow on thread destruction because
  49. // some code may still be executing in later TSD destructors
  50. // and we don't want it to have any poisoned stack.
  51. ClearShadowForThreadStackAndTLS();
  52. uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
  53. UnmapOrDie(this, size);
  54. DTLS_Destroy();
  55. }
  56. thread_return_t MsanThread::ThreadStart() {
  57. if (!start_routine_) {
  58. // start_routine_ == 0 if we're on the main thread or on one of the
  59. // OS X libdispatch worker threads. But nobody is supposed to call
  60. // ThreadStart() for the worker threads.
  61. return 0;
  62. }
  63. thread_return_t res = start_routine_(arg_);
  64. return res;
  65. }
  66. MsanThread::StackBounds MsanThread::GetStackBounds() const {
  67. if (!stack_switching_)
  68. return {stack_.bottom, stack_.top};
  69. const uptr cur_stack = GET_CURRENT_FRAME();
  70. // Note: need to check next stack first, because FinishSwitchFiber
  71. // may be in process of overwriting stack_.top/bottom_. But in such case
  72. // we are already on the next stack.
  73. if (cur_stack >= next_stack_.bottom && cur_stack < next_stack_.top)
  74. return {next_stack_.bottom, next_stack_.top};
  75. return {stack_.bottom, stack_.top};
  76. }
  77. uptr MsanThread::stack_top() { return GetStackBounds().top; }
  78. uptr MsanThread::stack_bottom() { return GetStackBounds().bottom; }
  79. bool MsanThread::AddrIsInStack(uptr addr) {
  80. const auto bounds = GetStackBounds();
  81. return addr >= bounds.bottom && addr < bounds.top;
  82. }
  83. void MsanThread::StartSwitchFiber(uptr bottom, uptr size) {
  84. CHECK(!stack_switching_);
  85. next_stack_.bottom = bottom;
  86. next_stack_.top = bottom + size;
  87. stack_switching_ = true;
  88. }
  89. void MsanThread::FinishSwitchFiber(uptr *bottom_old, uptr *size_old) {
  90. CHECK(stack_switching_);
  91. if (bottom_old)
  92. *bottom_old = stack_.bottom;
  93. if (size_old)
  94. *size_old = stack_.top - stack_.bottom;
  95. stack_.bottom = next_stack_.bottom;
  96. stack_.top = next_stack_.top;
  97. stack_switching_ = false;
  98. next_stack_.top = 0;
  99. next_stack_.bottom = 0;
  100. }
  101. } // namespace __msan