[asan] Optimize Quarantine of secondary allocations
authorVitaly Buka <vitalybuka@google.com>
Thu, 22 Jun 2023 05:44:56 +0000 (22:44 -0700)
committerVitaly Buka <vitalybuka@google.com>
Thu, 22 Jun 2023 18:24:08 +0000 (11:24 -0700)
For the secondary allocation we don't need poison and fill memory if we
skip quarantine, and we don't need to poison after quarantine. In both
cases the secondary allocator will unmap memory and unpoison the shadow
from get_allocator().Deallocate().

Depends on D153496.

Reviewed By: thurston

Differential Revision: https://reviews.llvm.org/D153497

compiler-rt/lib/asan/asan_allocator.cpp

index 70c6cbe..1e3c67b 100644 (file)
@@ -221,20 +221,26 @@ struct QuarantineCallback {
 
   void Recycle(AsanChunk *m) const {
     void *p = get_allocator().GetBlockBegin(m);
-    if (p != m) {
-      // Clear the magic value, as allocator internals may overwrite the
-      // contents of deallocated chunk, confusing GetAsanChunk lookup.
-      reinterpret_cast<LargeChunkHeader *>(p)->Set(nullptr);
-    }
 
-    u8 old_chunk_state = CHUNK_QUARANTINE;
-    if (!atomic_compare_exchange_strong(&m->chunk_state, &old_chunk_state,
-                                        CHUNK_INVALID, memory_order_acquire)) {
-      CHECK_EQ(old_chunk_state, CHUNK_QUARANTINE);
-    }
+    // The secondary will immediately unpoison and unmap the memory, so this
+    // branch is unnecessary.
+    if (get_allocator().FromPrimary(p)) {
+      if (p != m) {
+        // Clear the magic value, as allocator internals may overwrite the
+        // contents of deallocated chunk, confusing GetAsanChunk lookup.
+        reinterpret_cast<LargeChunkHeader *>(p)->Set(nullptr);
+      }
 
-    PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
-                 kAsanHeapLeftRedzoneMagic);
+      u8 old_chunk_state = CHUNK_QUARANTINE;
+      if (!atomic_compare_exchange_strong(&m->chunk_state, &old_chunk_state,
+                                          CHUNK_INVALID,
+                                          memory_order_acquire)) {
+        CHECK_EQ(old_chunk_state, CHUNK_QUARANTINE);
+      }
+
+      PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
+                   kAsanHeapLeftRedzoneMagic);
+    }
 
     // Statistics.
     AsanStats &thread_stats = GetCurrentThreadStats();
@@ -245,8 +251,12 @@ struct QuarantineCallback {
   }
 
   void RecyclePassThrough(AsanChunk *m) const {
-    // TODO: We don't need all these here.
-    PreQuarantine(m);
+    // Recycle for the secondary will immediately unpoison and unmap the
+    // memory, so quarantine preparation is unnecessary.
+    if (get_allocator().FromPrimary(m)) {
+      // The primary allocation may need pattern fill if enabled.
+      FillChunk(m);
+    }
     Recycle(m);
   }