[compiler-rt] dc7498e - [hwasan] Record allocation thread id in HeapAllocationRecord

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 3 20:26:13 PDT 2023


Author: Enna1
Date: 2023-04-04T11:25:18+08:00
New Revision: dc7498eb027b512091159731163327a0ff4f182e

URL: https://github.com/llvm/llvm-project/commit/dc7498eb027b512091159731163327a0ff4f182e
DIFF: https://github.com/llvm/llvm-project/commit/dc7498eb027b512091159731163327a0ff4f182e.diff

LOG: [hwasan] Record allocation thread id in HeapAllocationRecord

Extend HeapAllocationRecord to record allocation thread id, print thread id in memory allocation stack trace.

Reviewed By: vitalybuka

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

Added: 
    

Modified: 
    compiler-rt/lib/hwasan/hwasan_allocator.cpp
    compiler-rt/lib/hwasan/hwasan_allocator.h
    compiler-rt/lib/hwasan/hwasan_report.cpp
    compiler-rt/test/hwasan/TestCases/double-free.c
    compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp
    compiler-rt/test/hwasan/TestCases/realloc-after-free.c
    compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
    compiler-rt/test/hwasan/TestCases/tag_in_free.c
    compiler-rt/test/hwasan/TestCases/thread-uaf.c
    compiler-rt/test/hwasan/TestCases/use-after-free.c

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
index 994a580dc95e0..e6f46ed0933c1 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
@@ -64,6 +64,10 @@ u32 HwasanChunkView::GetAllocStackId() const {
   return metadata_->GetAllocStackId();
 }
 
+u32 HwasanChunkView::GetAllocThreadId() const {
+  return metadata_->GetAllocThreadId();
+}
+
 uptr HwasanChunkView::ActualSize() const {
   return allocator.GetActuallyAllocatedSize(reinterpret_cast<void *>(block_));
 }
@@ -106,6 +110,12 @@ inline u32 Metadata::GetAllocStackId() const {
   return atomic_load(&alloc_context_id, memory_order_relaxed);
 }
 
+inline u32 Metadata::GetAllocThreadId() const {
+  u64 context = atomic_load(&alloc_context_id, memory_order_relaxed);
+  u32 tid = context >> 32;
+  return tid;
+}
+
 void GetAllocatorStats(AllocatorStatCounters s) {
   allocator.GetStats(s);
 }
@@ -296,6 +306,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
   uptr orig_size = meta->GetRequestedSize();
   u32 free_context_id = StackDepotPut(*stack);
   u32 alloc_context_id = meta->GetAllocStackId();
+  u32 alloc_thread_id = meta->GetAllocThreadId();
 
   // Check tail magic.
   uptr tagged_size = TaggedSize(orig_size);
@@ -347,8 +358,9 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
   if (t) {
     allocator.Deallocate(t->allocator_cache(), aligned_ptr);
     if (auto *ha = t->heap_allocations())
-      ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_context_id,
-                free_context_id, static_cast<u32>(orig_size)});
+      ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_thread_id,
+                alloc_context_id, free_context_id,
+                static_cast<u32>(orig_size)});
   } else {
     SpinMutexLock l(&fallback_mutex);
     AllocatorCache *cache = &fallback_allocator_cache;

diff  --git a/compiler-rt/lib/hwasan/hwasan_allocator.h b/compiler-rt/lib/hwasan/hwasan_allocator.h
index 2093079413014..b7a06da0b6534 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.h
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.h
@@ -46,6 +46,7 @@ struct Metadata {
   inline bool IsAllocated() const;
   inline u64 GetRequestedSize() const;
   inline u32 GetAllocStackId() const;
+  inline u32 GetAllocThreadId() const;
   inline void SetLsanTag(__lsan::ChunkTag tag);
   inline __lsan::ChunkTag GetLsanTag() const;
 };
@@ -100,6 +101,7 @@ class HwasanChunkView {
   uptr UsedSize() const;       // Size requested by the user
   uptr ActualSize() const;     // Size allocated by the allocator.
   u32 GetAllocStackId() const;
+  u32 GetAllocThreadId() const;
   bool FromSmallHeap() const;
   bool AddrIsInside(uptr addr) const;
 
@@ -113,13 +115,12 @@ HwasanChunkView FindHeapChunkByAddress(uptr address);
 
 // Information about one (de)allocation that happened in the past.
 // These are recorded in a thread-local ring buffer.
-// TODO: this is currently 24 bytes (20 bytes + alignment).
-// Compress it to 16 bytes or extend it to be more useful.
 struct HeapAllocationRecord {
   uptr tagged_addr;
-  u32  alloc_context_id;
-  u32  free_context_id;
-  u32  requested_size;
+  u32 alloc_thread_id;
+  u32 alloc_context_id;
+  u32 free_context_id;
+  u32 requested_size;
 };
 
 typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;

diff  --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 31e190a8ebbcf..e720cb467a051 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -331,7 +331,7 @@ static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate,
            untagged_addr, offset, whence, chunk.UsedSize(), chunk.Beg(),
            chunk.End());
     Printf("%s", d.Allocation());
-    Printf("allocated here:\n");
+    Printf("allocated by thread T%u here:\n", chunk.GetAllocThreadId());
     Printf("%s", d.Default());
     GetStackTraceFromId(chunk.GetAllocStackId()).Print();
     return;
@@ -473,12 +473,12 @@ void PrintAddressDescription(
              har.requested_size, UntagAddr(har.tagged_addr),
              UntagAddr(har.tagged_addr) + har.requested_size);
       Printf("%s", d.Allocation());
-      Printf("freed by thread T%zd here:\n", t->unique_id());
+      Printf("freed by thread T%u here:\n", t->unique_id());
       Printf("%s", d.Default());
       GetStackTraceFromId(har.free_context_id).Print();
 
       Printf("%s", d.Allocation());
-      Printf("previously allocated here:\n", t);
+      Printf("previously allocated by thread T%u here:\n", har.alloc_thread_id);
       Printf("%s", d.Default());
       GetStackTraceFromId(har.alloc_context_id).Print();
 

diff  --git a/compiler-rt/test/hwasan/TestCases/double-free.c b/compiler-rt/test/hwasan/TestCases/double-free.c
index 6d177fdef7029..ec15dc300018f 100644
--- a/compiler-rt/test/hwasan/TestCases/double-free.c
+++ b/compiler-rt/test/hwasan/TestCases/double-free.c
@@ -18,7 +18,7 @@ int main() {
   // of the fault. With TCO the free frame can be replaced with the interceptor.
   // CHECK: in {{.*}}free
   // CHECK: freed by thread {{.*}} here:
-  // CHECK: previously allocated here:
+  // CHECK: previously allocated by thread {{.*}} here:
   // CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
   // CHECK: =>{{.*}}[[MEM_TAG]]
   fprintf(stderr, "DONE\n");

diff  --git a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp
index abd8bc42a34bb..2cb807cd3c762 100644
--- a/compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp
+++ b/compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp
@@ -18,7 +18,7 @@ int main(int argc, char **argv) {
   // LINKIFY: <a href="http://test.invalid/hwasan_symbolize.cpp:[[@LINE-1]]">
   // CHECK: hwasan_symbolize.cpp:[[@LINE-2]]
   // CHECK: Cause: heap-buffer-overflow
-  // CHECK: allocated here:
+  // CHECK: allocated by thread {{.*}} here:
   // LINKIFY: <a href="http://test.invalid/hwasan_symbolize.cpp:[[@LINE-6]]">
   // CHECK: hwasan_symbolize.cpp:[[@LINE-7]]
   return 0;

diff  --git a/compiler-rt/test/hwasan/TestCases/realloc-after-free.c b/compiler-rt/test/hwasan/TestCases/realloc-after-free.c
index c4bc48c9ccda2..393048c4eba9f 100644
--- a/compiler-rt/test/hwasan/TestCases/realloc-after-free.c
+++ b/compiler-rt/test/hwasan/TestCases/realloc-after-free.c
@@ -16,12 +16,12 @@ int main(int argc, char **argv) {
   char * volatile x = (char*)malloc(40);
   free(x);
   x = realloc(x, realloc_size);
-// CHECK: ERROR: HWAddressSanitizer: invalid-free on address
-// CHECK: tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
-// CHECK: freed by thread {{.*}} here:
-// CHECK: previously allocated here:
-// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
-// CHECK: =>{{.*}}[[MEM_TAG]]
+  // CHECK: ERROR: HWAddressSanitizer: invalid-free on address
+  // CHECK: tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+  // CHECK: freed by thread {{.*}} here:
+  // CHECK: previously allocated by thread {{.*}} here:
+  // CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
+  // CHECK: =>{{.*}}[[MEM_TAG]]
   fprintf(stderr, "DONE\n");
   __hwasan_disable_allocator_tagging();
 // CHECK-NOT: DONE

diff  --git a/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
index c2a20be75defc..42a57365d3914 100644
--- a/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
+++ b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
@@ -17,13 +17,13 @@ int main() {
   free(p);
   // CHECK: ERROR: HWAddressSanitizer:
   // CHECK: WRITE of size 1 at
-  // CHECK: allocated here:
+  // CHECK: allocated by thread {{.*}} here:
   // CHECK: Memory tags around the buggy address
 
   // CHECK: == error start
   // CHECK: ERROR: HWAddressSanitizer:
   // CHECK: WRITE of size 1 at
-  // CHECK: allocated here:
+  // CHECK: allocated by thread {{.*}} here:
   // CHECK: Memory tags around the buggy address
   // CHECK: == error end
 }

diff  --git a/compiler-rt/test/hwasan/TestCases/tag_in_free.c b/compiler-rt/test/hwasan/TestCases/tag_in_free.c
index 5c8dd65d56b7c..fba96dd188bac 100644
--- a/compiler-rt/test/hwasan/TestCases/tag_in_free.c
+++ b/compiler-rt/test/hwasan/TestCases/tag_in_free.c
@@ -33,7 +33,7 @@ int main() {
 #ifdef MALLOC
   // MALLOC: READ of size 1 at
   // MALLOC: is located 6 bytes after a 10-byte region
-  // MALLOC: allocated here:
+  // MALLOC: allocated by thread T0 here:
   char volatile x = p[16];
 #endif
   free(p);
@@ -41,7 +41,7 @@ int main() {
   // FREE: READ of size 1 at
   // FREE: is located 0 bytes inside a 10-byte region
   // FREE: freed by thread T0 here:
-  // FREE: previously allocated here:
+  // FREE: previously allocated by thread T0 here:
   char volatile y = p[0];
 #endif
 

diff  --git a/compiler-rt/test/hwasan/TestCases/thread-uaf.c b/compiler-rt/test/hwasan/TestCases/thread-uaf.c
index c368882f45896..478c1c98478ca 100644
--- a/compiler-rt/test/hwasan/TestCases/thread-uaf.c
+++ b/compiler-rt/test/hwasan/TestCases/thread-uaf.c
@@ -33,7 +33,7 @@ void *Use(void *arg) {
   // CHECK: Cause: use-after-free
   // CHECK: freed by thread T2 here
   // CHECK: in Deallocate
-  // CHECK: previously allocated here:
+  // CHECK: previously allocated by thread T1 here:
   // CHECK: in Allocate
   // CHECK-DAG: Thread: T2 0x
   // CHECK-DAG: Thread: T3 0x

diff  --git a/compiler-rt/test/hwasan/TestCases/use-after-free.c b/compiler-rt/test/hwasan/TestCases/use-after-free.c
index 24546374341e3..266e934e76f4b 100644
--- a/compiler-rt/test/hwasan/TestCases/use-after-free.c
+++ b/compiler-rt/test/hwasan/TestCases/use-after-free.c
@@ -35,7 +35,7 @@ int main() {
   // CHECK: #0 {{.*}} in {{.*}}free{{.*}} {{.*}}hwasan_allocation_functions.cpp
   // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-19]]
 
-  // CHECK: previously allocated here:
+  // CHECK: previously allocated by thread {{.*}} here:
   // CHECK: #0 {{.*}} in {{.*}}malloc{{.*}} {{.*}}hwasan_allocation_functions.cpp
   // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-24]]
   // CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):


        


More information about the llvm-commits mailing list