google / tcmalloc

Apache License 2.0
4.41k stars 480 forks source link

GWP-ASan may report segv in multi-thread when write_overflow/double_free detected at free? #240

Closed yejw5 closed 4 months ago

yejw5 commented 6 months ago

When double free or write overflow detected in GuardedPageAllocator::Deallocate, the double_freedetected or write_overflowdetected will assign true and trigger SEGV. Before SEGV handler exiting, there maybe other threads run into Deallocate and take write_overflow_detected_ || double_free_detected_, which trigger SEGV handler again. Even the non-first SEGV event have non memory error. If one real error SEGV along with multi false-positive triggering, the backtrace collected maybe confused

Refer to: GuardedPageAllocator::Deallocate implementation

void GuardedPageAllocator::Deallocate(void* ptr) {
  TC_ASSERT(PointerIsMine(ptr));
  const uintptr_t page_addr = GetPageAddr(reinterpret_cast<uintptr_t>(ptr));
  size_t slot = AddrToSlot(page_addr);

  {
    AllocationGuardSpinLockHolder h(&guarded_page_lock_);
    if (IsFreed(slot)) {
      double_free_detected_ = true;
    } else if (WriteOverflowOccurred(slot)) {
      write_overflow_detected_ = true;
    }

    TC_CHECK_EQ(
        0, mprotect(reinterpret_cast<void*>(page_addr), page_size_, PROT_NONE));
  }

  if (write_overflow_detected_ || double_free_detected_) {
    *reinterpret_cast<char*>(ptr) = 'X';  // Trigger SEGV handler.
    TC_BUG("unreachable");
  }

  ...