tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sanitizer_deadlock_suppression.patch (3259B)


      1 Add support for suppressing corner cases of recursive locking that TSAN
      2 normally doesn't allow.
      3 
      4 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp
      5 index ccb7065b07ae..58cfc5e1a1fb 100644
      6 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp
      7 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp
      8 @@ -15,6 +15,7 @@
      9 #include "sanitizer_allocator_internal.h"
     10 #include "sanitizer_placement_new.h"
     11 #include "sanitizer_mutex.h"
     12 +#include "sanitizer_stackdepot.h"
     13 
     14 #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
     15 
     16 @@ -162,8 +163,19 @@ void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
     17 
     18   SpinMutexLock lk(&mtx);
     19   MutexEnsureID(lt, m);
     20 -  if (wlock)  // Only a recursive rlock may be held.
     21 -    CHECK(!dd.isHeld(&lt->dd, m->id));
     22 +  // Only a recursive rlock may be held.
     23 +  if (wlock && dd.isHeld(&lt->dd, m->id)) {
     24 +    // Get stack traces from where the lock is already held.
     25 +    u32 held_stk = dd.findLockContext(&lt->dd, m->id);
     26 +    if (!cb->IsDeadlockSuppressed(held_stk)) {
     27 +      stk = stk ? stk : cb->Unwind();
     28 +      if (!cb->IsDeadlockSuppressed(stk)) {
     29 +        // We could avoid calling this twice, by storing the result above, but
     30 +        // we do want the error message to be unchanged.
     31 +        CHECK(!dd.isHeld(&lt->dd, m->id));
     32 +      }
     33 +    }
     34 +  }
     35   if (!trylock)
     36     dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
     37   dd.onLockAfter(&lt->dd, m->id, stk);
     38 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
     39 index 7f461c98bade..252e62e05622 100644
     40 --- a/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
     41 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
     42 @@ -66,6 +66,7 @@ struct DDCallback {
     43 
     44   virtual u32 Unwind() { return 0; }
     45   virtual int UniqueTid() { return 0; }
     46 +  virtual bool IsDeadlockSuppressed(u32 stk) { return false; }
     47 
     48  protected:
     49   ~DDCallback() {}
     50 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
     51 index 2a8aa1915c9a..1df8acfd7fd0 100644
     52 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
     53 +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
     54 @@ -15,8 +15,10 @@
     55 
     56 #include "tsan_rtl.h"
     57 #include "tsan_flags.h"
     58 +#include "tsan_mman.h"
     59 #include "tsan_sync.h"
     60 #include "tsan_report.h"
     61 +#include "tsan_suppressions.h"
     62 #include "tsan_symbolize.h"
     63 #include "tsan_platform.h"
     64 
     65 @@ -39,6 +41,21 @@ struct Callback final : public DDCallback {
     66 
     67   StackID Unwind() override { return CurrentStackId(thr, pc); }
     68   int UniqueTid() override { return thr->tid; }
     69 +
     70 +  bool IsDeadlockSuppressed(u32 stk) override {
     71 +    bool result = false;
     72 +    if (stk) {
     73 +      Suppression *supp = nullptr;
     74 +      ReportStack *rs = SymbolizeStackId(stk);
     75 +      rs->suppressable = true;
     76 +      result = IsSuppressed(ReportTypeDeadlock, rs, &supp);
     77 +      if (rs->frames) {
     78 +        rs->frames->ClearAll();
     79 +      }
     80 +      DestroyAndFree(rs);
     81 +    }
     82 +    return result;
     83 +  }
     84 };
     85 
     86 void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {