[compiler-rt] r340971 - Add a thread-local ring buffer of heap allocations

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 29 14:07:07 PDT 2018


Author: kcc
Date: Wed Aug 29 14:07:07 2018
New Revision: 340971

URL: http://llvm.org/viewvc/llvm-project?rev=340971&view=rev
Log:
Add a thread-local ring buffer of heap allocations

Summary:
We need this in order to properly report heap-use-after-free,
since we don't have a quarantine.

This is a first part of the code, more like a proof of concept.
But I'd like to commit at as is and proceed with refactoring,
adding a ThreadRegistry, and extending the functionality.

Reviewers: eugenis

Subscribers: kubamracek, delcypher, #sanitizers, llvm-commits

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

Modified:
    compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
    compiler-rt/trunk/lib/hwasan/hwasan_allocator.h
    compiler-rt/trunk/lib/hwasan/hwasan_flags.inc
    compiler-rt/trunk/lib/hwasan/hwasan_report.cc
    compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
    compiler-rt/trunk/lib/hwasan/hwasan_thread.h

Modified: compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc Wed Aug 29 14:07:07 2018
@@ -36,7 +36,7 @@ enum {
 
 struct Metadata {
   u64 state : 2;
-  u64 requested_size : 62;
+  u32 requested_size;  // Current use cases of hwasan do not expect sizes > 4G.
   u32 alloc_context_id;
   u32 free_context_id;
 };
@@ -155,7 +155,7 @@ static void *HwasanAllocate(StackTrace *
   Metadata *meta =
       reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
   meta->state = CHUNK_ALLOCATED;
-  meta->requested_size = size;
+  meta->requested_size = static_cast<u32>(size);
   meta->alloc_context_id = StackDepotPut(*stack);
   if (zeroise) {
     internal_memset(allocated, 0, size);
@@ -194,7 +194,8 @@ void HwasanDeallocate(StackTrace *stack,
   uptr size = meta->requested_size;
   meta->state = CHUNK_FREE;
   meta->requested_size = 0;
-  meta->free_context_id = StackDepotPut(*stack);
+  u32 free_context_id = StackDepotPut(*stack);
+  meta->free_context_id = free_context_id;
   // This memory will not be reused by anyone else, so we are free to keep it
   // poisoned.
   HwasanThread *t = GetCurrentThread();
@@ -209,6 +210,9 @@ void HwasanDeallocate(StackTrace *stack,
   if (t) {
     AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
     allocator.Deallocate(cache, p);
+    if (auto *ha = t->heap_allocations())
+      ha->push({reinterpret_cast<uptr>(user_ptr), free_context_id,
+                static_cast<u32>(size)});
   } else {
     SpinMutexLock l(&fallback_mutex);
     AllocatorCache *cache = &fallback_allocator_cache;
@@ -252,6 +256,7 @@ void *HwasanReallocate(StackTrace *stack
     internal_memcpy(new_p, old_p, memcpy_size);
     HwasanDeallocate(stack, old_p);
   }
+  // FIXME: update t->heap_allocations or simplify HwasanReallocate.
   return new_p;
 }
 

Modified: compiler-rt/trunk/lib/hwasan/hwasan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_allocator.h?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_allocator.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_allocator.h Wed Aug 29 14:07:07 2018
@@ -15,6 +15,7 @@
 #define HWASAN_ALLOCATOR_H
 
 #include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_ring_buffer.h"
 
 namespace __hwasan {
 
@@ -49,6 +50,17 @@ class HwasanChunkView {
 
 HwasanChunkView FindHeapChunkByAddress(uptr address);
 
+// Information about one (de)allocation that happened in the past.
+// These are recorded in a thread-local ring buffer.
+struct HeapAllocationRecord {
+  uptr tagged_addr;
+  u32  free_context_id;
+  u32  requested_size;
+};
+
+typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;
+
+
 } // namespace __hwasan
 
 #endif // HWASAN_ALLOCATOR_H

Modified: compiler-rt/trunk/lib/hwasan/hwasan_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_flags.inc?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_flags.inc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_flags.inc Wed Aug 29 14:07:07 2018
@@ -44,3 +44,7 @@ HWASAN_FLAG(int, malloc_fill_byte, 0xbe,
           "Value used to fill the newly allocated memory.")
 HWASAN_FLAG(int, free_fill_byte, 0x55,
           "Value used to fill deallocated memory.")
+HWASAN_FLAG(int, heap_history_size, 1023,
+          "The number of heap (de)allocations remembered per thread. "
+          "Affects the quality of heap-related reports, but not the ability "
+          "to find bugs.")

Modified: compiler-rt/trunk/lib/hwasan/hwasan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_report.cc?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Wed Aug 29 14:07:07 2018
@@ -15,6 +15,7 @@
 #include "hwasan.h"
 #include "hwasan_allocator.h"
 #include "hwasan_mapping.h"
+#include "hwasan_thread.h"
 #include "sanitizer_common/sanitizer_allocator_internal.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
@@ -61,6 +62,21 @@ struct HeapAddressDescription {
   }
 };
 
+bool FindHeapAllocation(HeapAllocationsRingBuffer *rb,
+                        uptr tagged_addr,
+                        HeapAllocationRecord *har) {
+  if (!rb) return false;
+  for (uptr i = 0, size = rb->size(); i < size; i++) {
+    auto h = (*rb)[i];
+    if (h.tagged_addr <= tagged_addr &&
+        h.tagged_addr + h.requested_size > tagged_addr) {
+      *har = h;
+      return true;
+    }
+  }
+  return false;
+}
+
 bool GetHeapAddressInformation(uptr addr, uptr access_size,
                                HeapAddressDescription *description) {
   HwasanChunkView chunk = FindHeapChunkByAddress(addr);
@@ -182,6 +198,18 @@ void ReportTagMismatch(StackTrace *stack
 
   PrintAddressDescription(address, access_size);
 
+  // Temporary functionality; to be folded into PrintAddressDescription.
+  // TODOs:
+  // * implement ThreadRegistry
+  // * check all threads, not just the current one.
+  // * remove reduntant fields from the allocator metadata
+  // * use the allocations found in the ring buffer for the main report.
+  HeapAllocationRecord har;
+  HwasanThread *t = GetCurrentThread();
+  if (t && FindHeapAllocation(t->heap_allocations(), addr, &har))
+    Printf("Address found in the ring buffer: %p %u %u\n", har.tagged_addr,
+           har.free_context_id, har.requested_size);
+
   PrintTagsAroundAddr(tag_ptr);
 
   ReportErrorSummary(bug_type, stack);

Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.cc?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.cc Wed Aug 29 14:07:07 2018
@@ -32,7 +32,8 @@ HwasanThread *HwasanThread::Create(threa
   thread->arg_ = arg;
   thread->destructor_iterations_ = GetPthreadDestructorIterations();
   thread->random_state_ = flags()->random_tags ? RandomSeed() : 0;
-
+  if (auto sz = flags()->heap_history_size)
+    thread->heap_allocations_ = RingBuffer<HeapAllocationRecord>::New(sz);
   return thread;
 }
 
@@ -76,6 +77,8 @@ void HwasanThread::Destroy() {
   malloc_storage().CommitBack();
   ClearShadowForThreadStackAndTLS();
   uptr size = RoundUpTo(sizeof(HwasanThread), GetPageSizeCached());
+  if (heap_allocations_)
+    heap_allocations_->Delete();
   UnmapOrDie(this, size);
   DTLS_Destroy();
 }

Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.h?rev=340971&r1=340970&r2=340971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.h Wed Aug 29 14:07:07 2018
@@ -50,6 +50,9 @@ class HwasanThread {
   void LeaveInterceptorScope() { in_interceptor_scope_--; }
 
   HwasanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+  HeapAllocationsRingBuffer *heap_allocations() {
+    return heap_allocations_;
+  }
 
   tag_t GenerateRandomTag();
 
@@ -75,6 +78,7 @@ class HwasanThread {
   u32 random_buffer_;
 
   HwasanThreadLocalMallocStorage malloc_storage_;
+  HeapAllocationsRingBuffer *heap_allocations_;
 };
 
 HwasanThread *GetCurrentThread();




More information about the llvm-commits mailing list