From ee9bb8761c4bf51658a806641fff3e452d3116f5 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 12 Sep 2018 00:58:15 +0000 Subject: [PATCH] [hwasan] On every use-after-free print a developer note: the index of this heap object in the thread's deallocation ring buffer. Mostly useful to hwasan developers, will hopefully let us know the good size of the deallocation ring buffer llvm-svn: 342014 --- compiler-rt/lib/hwasan/hwasan_report.cc | 17 ++++++++---- .../hwasan/TestCases/uaf_with_rb_distance.c | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 compiler-rt/test/hwasan/TestCases/uaf_with_rb_distance.c diff --git a/compiler-rt/lib/hwasan/hwasan_report.cc b/compiler-rt/lib/hwasan/hwasan_report.cc index 60eb5c1a498b..4c6c8b931bfb 100644 --- a/compiler-rt/lib/hwasan/hwasan_report.cc +++ b/compiler-rt/lib/hwasan/hwasan_report.cc @@ -46,19 +46,21 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator { const char *Thread() { return Green(); } }; -bool FindHeapAllocation(HeapAllocationsRingBuffer *rb, +// Returns the index of the rb element that matches tagged_addr (plus one), +// or zero if found nothing. +uptr FindHeapAllocation(HeapAllocationsRingBuffer *rb, uptr tagged_addr, HeapAllocationRecord *har) { - if (!rb) return false; + if (!rb) return 0; 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 i + 1; } } - return false; + return 0; } void PrintAddressDescription(uptr tagged_addr, uptr access_size) { @@ -110,7 +112,7 @@ void PrintAddressDescription(uptr tagged_addr, uptr access_size) { Thread::VisitAllLiveThreads([&](Thread *t) { // Scan all threads' ring buffers to find if it's a heap-use-after-free. HeapAllocationRecord har; - if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) { + if (uptr D = FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) { Printf("%s", d.Location()); Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n", untagged_addr, untagged_addr - UntagAddr(har.tagged_addr), @@ -127,6 +129,11 @@ void PrintAddressDescription(uptr tagged_addr, uptr access_size) { GetStackTraceFromId(har.alloc_context_id).Print(); t->Announce(); + // Print a developer note: the index of this heap object + // in the thread's deallocation ring buffer. + Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", D, + flags()->heap_history_size); + num_descriptions_printed++; } diff --git a/compiler-rt/test/hwasan/TestCases/uaf_with_rb_distance.c b/compiler-rt/test/hwasan/TestCases/uaf_with_rb_distance.c new file mode 100644 index 000000000000..25aae5256c41 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/uaf_with_rb_distance.c @@ -0,0 +1,27 @@ +// Checks how we print the developer note "hwasan_dev_note_heap_rb_distance". +// RUN: %clang_hwasan %s -o %t +// RUN: not %run %t 10 2>&1 | FileCheck %s --check-prefix=D10 +// RUN: not %run %t 42 2>&1 | FileCheck %s --check-prefix=D42 + +// REQUIRES: stable-runtime + +#include +#include +#include + + +void *p[100]; + +int main(int argc, char **argv) { + __hwasan_enable_allocator_tagging(); + int distance = argc >= 2 ? atoi(argv[1]) : 1; + for (int i = 0; i < 100; i++) + p[i] = malloc(i); + for (int i = 0; i < 100; i++) + free(p[i]); + + *(int*)p[distance] = 0; +} + +// D10: hwasan_dev_note_heap_rb_distance: 90 1023 +// D42: hwasan_dev_note_heap_rb_distance: 58 1023 -- 2.34.1