Skip to content

Commit dc7498e

Browse files
committed
[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
1 parent 329cb1d commit dc7498e

File tree

10 files changed

+37
-24
lines changed

10 files changed

+37
-24
lines changed

compiler-rt/lib/hwasan/hwasan_allocator.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ u32 HwasanChunkView::GetAllocStackId() const {
6464
return metadata_->GetAllocStackId();
6565
}
6666

67+
u32 HwasanChunkView::GetAllocThreadId() const {
68+
return metadata_->GetAllocThreadId();
69+
}
70+
6771
uptr HwasanChunkView::ActualSize() const {
6872
return allocator.GetActuallyAllocatedSize(reinterpret_cast<void *>(block_));
6973
}
@@ -106,6 +110,12 @@ inline u32 Metadata::GetAllocStackId() const {
106110
return atomic_load(&alloc_context_id, memory_order_relaxed);
107111
}
108112

113+
inline u32 Metadata::GetAllocThreadId() const {
114+
u64 context = atomic_load(&alloc_context_id, memory_order_relaxed);
115+
u32 tid = context >> 32;
116+
return tid;
117+
}
118+
109119
void GetAllocatorStats(AllocatorStatCounters s) {
110120
allocator.GetStats(s);
111121
}
@@ -296,6 +306,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
296306
uptr orig_size = meta->GetRequestedSize();
297307
u32 free_context_id = StackDepotPut(*stack);
298308
u32 alloc_context_id = meta->GetAllocStackId();
309+
u32 alloc_thread_id = meta->GetAllocThreadId();
299310

300311
// Check tail magic.
301312
uptr tagged_size = TaggedSize(orig_size);
@@ -347,8 +358,9 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
347358
if (t) {
348359
allocator.Deallocate(t->allocator_cache(), aligned_ptr);
349360
if (auto *ha = t->heap_allocations())
350-
ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_context_id,
351-
free_context_id, static_cast<u32>(orig_size)});
361+
ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_thread_id,
362+
alloc_context_id, free_context_id,
363+
static_cast<u32>(orig_size)});
352364
} else {
353365
SpinMutexLock l(&fallback_mutex);
354366
AllocatorCache *cache = &fallback_allocator_cache;

compiler-rt/lib/hwasan/hwasan_allocator.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct Metadata {
4646
inline bool IsAllocated() const;
4747
inline u64 GetRequestedSize() const;
4848
inline u32 GetAllocStackId() const;
49+
inline u32 GetAllocThreadId() const;
4950
inline void SetLsanTag(__lsan::ChunkTag tag);
5051
inline __lsan::ChunkTag GetLsanTag() const;
5152
};
@@ -100,6 +101,7 @@ class HwasanChunkView {
100101
uptr UsedSize() const; // Size requested by the user
101102
uptr ActualSize() const; // Size allocated by the allocator.
102103
u32 GetAllocStackId() const;
104+
u32 GetAllocThreadId() const;
103105
bool FromSmallHeap() const;
104106
bool AddrIsInside(uptr addr) const;
105107

@@ -113,13 +115,12 @@ HwasanChunkView FindHeapChunkByAddress(uptr address);
113115

114116
// Information about one (de)allocation that happened in the past.
115117
// These are recorded in a thread-local ring buffer.
116-
// TODO: this is currently 24 bytes (20 bytes + alignment).
117-
// Compress it to 16 bytes or extend it to be more useful.
118118
struct HeapAllocationRecord {
119119
uptr tagged_addr;
120-
u32 alloc_context_id;
121-
u32 free_context_id;
122-
u32 requested_size;
120+
u32 alloc_thread_id;
121+
u32 alloc_context_id;
122+
u32 free_context_id;
123+
u32 requested_size;
123124
};
124125

125126
typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;

compiler-rt/lib/hwasan/hwasan_report.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate,
331331
untagged_addr, offset, whence, chunk.UsedSize(), chunk.Beg(),
332332
chunk.End());
333333
Printf("%s", d.Allocation());
334-
Printf("allocated here:\n");
334+
Printf("allocated by thread T%u here:\n", chunk.GetAllocThreadId());
335335
Printf("%s", d.Default());
336336
GetStackTraceFromId(chunk.GetAllocStackId()).Print();
337337
return;
@@ -473,12 +473,12 @@ void PrintAddressDescription(
473473
har.requested_size, UntagAddr(har.tagged_addr),
474474
UntagAddr(har.tagged_addr) + har.requested_size);
475475
Printf("%s", d.Allocation());
476-
Printf("freed by thread T%zd here:\n", t->unique_id());
476+
Printf("freed by thread T%u here:\n", t->unique_id());
477477
Printf("%s", d.Default());
478478
GetStackTraceFromId(har.free_context_id).Print();
479479

480480
Printf("%s", d.Allocation());
481-
Printf("previously allocated here:\n", t);
481+
Printf("previously allocated by thread T%u here:\n", har.alloc_thread_id);
482482
Printf("%s", d.Default());
483483
GetStackTraceFromId(har.alloc_context_id).Print();
484484

compiler-rt/test/hwasan/TestCases/double-free.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ int main() {
1818
// of the fault. With TCO the free frame can be replaced with the interceptor.
1919
// CHECK: in {{.*}}free
2020
// CHECK: freed by thread {{.*}} here:
21-
// CHECK: previously allocated here:
21+
// CHECK: previously allocated by thread {{.*}} here:
2222
// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
2323
// CHECK: =>{{.*}}[[MEM_TAG]]
2424
fprintf(stderr, "DONE\n");

compiler-rt/test/hwasan/TestCases/hwasan_symbolize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ int main(int argc, char **argv) {
1818
// LINKIFY: <a href="http://test.invalid/hwasan_symbolize.cpp:[[@LINE-1]]">
1919
// CHECK: hwasan_symbolize.cpp:[[@LINE-2]]
2020
// CHECK: Cause: heap-buffer-overflow
21-
// CHECK: allocated here:
21+
// CHECK: allocated by thread {{.*}} here:
2222
// LINKIFY: <a href="http://test.invalid/hwasan_symbolize.cpp:[[@LINE-6]]">
2323
// CHECK: hwasan_symbolize.cpp:[[@LINE-7]]
2424
return 0;

compiler-rt/test/hwasan/TestCases/realloc-after-free.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ int main(int argc, char **argv) {
1616
char * volatile x = (char*)malloc(40);
1717
free(x);
1818
x = realloc(x, realloc_size);
19-
// CHECK: ERROR: HWAddressSanitizer: invalid-free on address
20-
// CHECK: tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
21-
// CHECK: freed by thread {{.*}} here:
22-
// CHECK: previously allocated here:
23-
// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
24-
// CHECK: =>{{.*}}[[MEM_TAG]]
19+
// CHECK: ERROR: HWAddressSanitizer: invalid-free on address
20+
// CHECK: tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
21+
// CHECK: freed by thread {{.*}} here:
22+
// CHECK: previously allocated by thread {{.*}} here:
23+
// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
24+
// CHECK: =>{{.*}}[[MEM_TAG]]
2525
fprintf(stderr, "DONE\n");
2626
__hwasan_disable_allocator_tagging();
2727
// CHECK-NOT: DONE

compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ int main() {
1717
free(p);
1818
// CHECK: ERROR: HWAddressSanitizer:
1919
// CHECK: WRITE of size 1 at
20-
// CHECK: allocated here:
20+
// CHECK: allocated by thread {{.*}} here:
2121
// CHECK: Memory tags around the buggy address
2222

2323
// CHECK: == error start
2424
// CHECK: ERROR: HWAddressSanitizer:
2525
// CHECK: WRITE of size 1 at
26-
// CHECK: allocated here:
26+
// CHECK: allocated by thread {{.*}} here:
2727
// CHECK: Memory tags around the buggy address
2828
// CHECK: == error end
2929
}

compiler-rt/test/hwasan/TestCases/tag_in_free.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ int main() {
3333
#ifdef MALLOC
3434
// MALLOC: READ of size 1 at
3535
// MALLOC: is located 6 bytes after a 10-byte region
36-
// MALLOC: allocated here:
36+
// MALLOC: allocated by thread T0 here:
3737
char volatile x = p[16];
3838
#endif
3939
free(p);
4040
#ifdef FREE
4141
// FREE: READ of size 1 at
4242
// FREE: is located 0 bytes inside a 10-byte region
4343
// FREE: freed by thread T0 here:
44-
// FREE: previously allocated here:
44+
// FREE: previously allocated by thread T0 here:
4545
char volatile y = p[0];
4646
#endif
4747

compiler-rt/test/hwasan/TestCases/thread-uaf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void *Use(void *arg) {
3333
// CHECK: Cause: use-after-free
3434
// CHECK: freed by thread T2 here
3535
// CHECK: in Deallocate
36-
// CHECK: previously allocated here:
36+
// CHECK: previously allocated by thread T1 here:
3737
// CHECK: in Allocate
3838
// CHECK-DAG: Thread: T2 0x
3939
// CHECK-DAG: Thread: T3 0x

compiler-rt/test/hwasan/TestCases/use-after-free.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ int main() {
3535
// CHECK: #0 {{.*}} in {{.*}}free{{.*}} {{.*}}hwasan_allocation_functions.cpp
3636
// CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-19]]
3737

38-
// CHECK: previously allocated here:
38+
// CHECK: previously allocated by thread {{.*}} here:
3939
// CHECK: #0 {{.*}} in {{.*}}malloc{{.*}} {{.*}}hwasan_allocation_functions.cpp
4040
// CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-24]]
4141
// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):

0 commit comments

Comments
 (0)