1616#include " hwasan_allocator.h"
1717#include " hwasan_mapping.h"
1818#include " hwasan_thread.h"
19+ #include " hwasan_thread_list.h"
1920#include " sanitizer_common/sanitizer_allocator_internal.h"
2021#include " sanitizer_common/sanitizer_common.h"
2122#include " sanitizer_common/sanitizer_flags.h"
@@ -35,6 +36,31 @@ static StackTrace GetStackTraceFromId(u32 id) {
3536 return res;
3637}
3738
39+ // A RAII object that holds a copy of the current thread stack ring buffer.
40+ // The actual stack buffer may change while we are iterating over it (for
41+ // example, Printf may call syslog() which can itself be built with hwasan).
42+ class SavedStackAllocations {
43+ public:
44+ SavedStackAllocations (StackAllocationsRingBuffer *rb) {
45+ uptr size = rb->size () * sizeof (uptr);
46+ void *storage =
47+ MmapAlignedOrDieOnFatalError (size, size * 2 , " saved stack allocations" );
48+ new (&rb_) StackAllocationsRingBuffer (*rb, storage);
49+ }
50+
51+ ~SavedStackAllocations () {
52+ StackAllocationsRingBuffer *rb = get ();
53+ UnmapOrDie (rb->StartOfStorage (), rb->size () * sizeof (uptr));
54+ }
55+
56+ StackAllocationsRingBuffer *get () {
57+ return (StackAllocationsRingBuffer *)&rb_;
58+ }
59+
60+ private:
61+ uptr rb_;
62+ };
63+
3864class Decorator : public __sanitizer ::SanitizerCommonDecorator {
3965 public:
4066 Decorator () : SanitizerCommonDecorator() { }
@@ -63,7 +89,9 @@ uptr FindHeapAllocation(HeapAllocationsRingBuffer *rb,
6389 return 0 ;
6490}
6591
66- void PrintAddressDescription (uptr tagged_addr, uptr access_size) {
92+ void PrintAddressDescription (
93+ uptr tagged_addr, uptr access_size,
94+ StackAllocationsRingBuffer *current_stack_allocations) {
6795 Decorator d;
6896 int num_descriptions_printed = 0 ;
6997 uptr untagged_addr = UntagAddr (tagged_addr);
@@ -109,7 +137,7 @@ void PrintAddressDescription(uptr tagged_addr, uptr access_size) {
109137 }
110138 }
111139
112- Thread:: VisitAllLiveThreads ([&](Thread *t) {
140+ hwasanThreadList (). VisitAllLiveThreads ([&](Thread *t) {
113141 // Scan all threads' ring buffers to find if it's a heap-use-after-free.
114142 HeapAllocationRecord har;
115143 if (uptr D = FindHeapAllocation (t->heap_allocations (), tagged_addr, &har)) {
@@ -145,6 +173,25 @@ void PrintAddressDescription(uptr tagged_addr, uptr access_size) {
145173 Printf (" %s" , d.Default ());
146174 t->Announce ();
147175
176+ // Temporary report section, needs to be improved.
177+ Printf (" Previosly allocated frames:\n " );
178+ auto *sa = (t == GetCurrentThread () && current_stack_allocations)
179+ ? current_stack_allocations
180+ : t->stack_allocations ();
181+ uptr frames = Min ((uptr)flags ()->stack_history_size , sa->size ());
182+ for (uptr i = 0 ; i < frames; i++) {
183+ uptr record = (*sa)[i];
184+ if (!record)
185+ break ;
186+ uptr sp = (record >> 48 ) << 4 ;
187+ uptr pc_mask = (1ULL << 48 ) - 1 ;
188+ uptr pc = record & pc_mask;
189+ uptr fixed_pc = StackTrace::GetNextInstructionPc (pc);
190+ StackTrace stack (&fixed_pc, 1 );
191+ Printf (" record: %p pc: %p sp: %p" , record, pc, sp);
192+ stack.Print ();
193+ }
194+
148195 num_descriptions_printed++;
149196 }
150197 });
@@ -170,13 +217,16 @@ void ReportStats() {}
170217void ReportInvalidAccessInsideAddressRange (const char *what, const void *start,
171218 uptr size, uptr offset) {
172219 ScopedErrorReportLock l;
220+ SavedStackAllocations current_stack_allocations (
221+ GetCurrentThread ()->stack_allocations ());
173222
174223 Decorator d;
175224 Printf (" %s" , d.Warning ());
176225 Printf (" %sTag mismatch in %s%s%s at offset %zu inside [%p, %zu)%s\n " ,
177226 d.Warning (), d.Name (), what, d.Warning (), offset, start, size,
178227 d.Default ());
179- PrintAddressDescription ((uptr)start + offset, 1 );
228+ PrintAddressDescription ((uptr)start + offset, 1 ,
229+ current_stack_allocations.get ());
180230 // if (__sanitizer::Verbosity())
181231 // DescribeMemoryRange(start, size);
182232}
@@ -224,7 +274,7 @@ void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
224274
225275 stack->Print ();
226276
227- PrintAddressDescription (tagged_addr, 0 );
277+ PrintAddressDescription (tagged_addr, 0 , nullptr );
228278
229279 PrintTagsAroundAddr (tag_ptr);
230280
@@ -235,6 +285,8 @@ void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
235285void ReportTagMismatch (StackTrace *stack, uptr tagged_addr, uptr access_size,
236286 bool is_store) {
237287 ScopedErrorReportLock l;
288+ SavedStackAllocations current_stack_allocations (
289+ GetCurrentThread ()->stack_allocations ());
238290
239291 Decorator d;
240292 Printf (" %s" , d.Error ());
@@ -258,7 +310,8 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
258310
259311 stack->Print ();
260312
261- PrintAddressDescription (tagged_addr, access_size);
313+ PrintAddressDescription (tagged_addr, access_size,
314+ current_stack_allocations.get ());
262315 t->Announce ();
263316
264317 PrintTagsAroundAddr (tag_ptr);
0 commit comments