1 1.1 mrg //===-- hwasan_report.cpp -------------------------------------------------===// 2 1.1 mrg // 3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 mrg // 7 1.1 mrg //===----------------------------------------------------------------------===// 8 1.1 mrg // 9 1.1 mrg // This file is a part of HWAddressSanitizer. 10 1.1 mrg // 11 1.1 mrg // Error reporting. 12 1.1 mrg //===----------------------------------------------------------------------===// 13 1.1 mrg 14 1.1 mrg #include "hwasan_report.h" 15 1.1 mrg 16 1.1 mrg #include <dlfcn.h> 17 1.1 mrg 18 1.1 mrg #include "hwasan.h" 19 1.1 mrg #include "hwasan_allocator.h" 20 1.1 mrg #include "hwasan_globals.h" 21 1.1 mrg #include "hwasan_mapping.h" 22 1.1 mrg #include "hwasan_thread.h" 23 1.1 mrg #include "hwasan_thread_list.h" 24 1.1 mrg #include "sanitizer_common/sanitizer_allocator_internal.h" 25 1.1.1.2 mrg #include "sanitizer_common/sanitizer_array_ref.h" 26 1.1 mrg #include "sanitizer_common/sanitizer_common.h" 27 1.1 mrg #include "sanitizer_common/sanitizer_flags.h" 28 1.1.1.2 mrg #include "sanitizer_common/sanitizer_internal_defs.h" 29 1.1 mrg #include "sanitizer_common/sanitizer_mutex.h" 30 1.1 mrg #include "sanitizer_common/sanitizer_report_decorator.h" 31 1.1 mrg #include "sanitizer_common/sanitizer_stackdepot.h" 32 1.1 mrg #include "sanitizer_common/sanitizer_stacktrace_printer.h" 33 1.1 mrg #include "sanitizer_common/sanitizer_symbolizer.h" 34 1.1 mrg 35 1.1 mrg using namespace __sanitizer; 36 1.1 mrg 37 1.1 mrg namespace __hwasan { 38 1.1 mrg 39 1.1 mrg class ScopedReport { 40 1.1 mrg public: 41 1.1.1.2 mrg explicit ScopedReport(bool fatal) : fatal(fatal) { 42 1.1 mrg Lock lock(&error_message_lock_); 43 1.1 mrg error_message_ptr_ = fatal ? &error_message_ : nullptr; 44 1.1 mrg ++hwasan_report_count; 45 1.1 mrg } 46 1.1 mrg 47 1.1 mrg ~ScopedReport() { 48 1.1 mrg void (*report_cb)(const char *); 49 1.1 mrg { 50 1.1 mrg Lock lock(&error_message_lock_); 51 1.1 mrg report_cb = error_report_callback_; 52 1.1 mrg error_message_ptr_ = nullptr; 53 1.1 mrg } 54 1.1 mrg if (report_cb) 55 1.1 mrg report_cb(error_message_.data()); 56 1.1 mrg if (fatal) 57 1.1 mrg SetAbortMessage(error_message_.data()); 58 1.1 mrg if (common_flags()->print_module_map >= 2 || 59 1.1 mrg (fatal && common_flags()->print_module_map)) 60 1.1 mrg DumpProcessMap(); 61 1.1 mrg if (fatal) 62 1.1 mrg Die(); 63 1.1 mrg } 64 1.1 mrg 65 1.1 mrg static void MaybeAppendToErrorMessage(const char *msg) { 66 1.1 mrg Lock lock(&error_message_lock_); 67 1.1 mrg if (!error_message_ptr_) 68 1.1 mrg return; 69 1.1.1.2 mrg error_message_ptr_->Append(msg); 70 1.1 mrg } 71 1.1 mrg 72 1.1 mrg static void SetErrorReportCallback(void (*callback)(const char *)) { 73 1.1 mrg Lock lock(&error_message_lock_); 74 1.1 mrg error_report_callback_ = callback; 75 1.1 mrg } 76 1.1 mrg 77 1.1 mrg private: 78 1.1.1.2 mrg InternalScopedString error_message_; 79 1.1 mrg bool fatal; 80 1.1 mrg 81 1.1 mrg static Mutex error_message_lock_; 82 1.1.1.2 mrg static InternalScopedString *error_message_ptr_ 83 1.1.1.2 mrg SANITIZER_GUARDED_BY(error_message_lock_); 84 1.1 mrg static void (*error_report_callback_)(const char *); 85 1.1 mrg }; 86 1.1 mrg 87 1.1 mrg Mutex ScopedReport::error_message_lock_; 88 1.1.1.2 mrg InternalScopedString *ScopedReport::error_message_ptr_; 89 1.1 mrg void (*ScopedReport::error_report_callback_)(const char *); 90 1.1 mrg 91 1.1 mrg // If there is an active ScopedReport, append to its error message. 92 1.1 mrg void AppendToErrorMessageBuffer(const char *buffer) { 93 1.1 mrg ScopedReport::MaybeAppendToErrorMessage(buffer); 94 1.1 mrg } 95 1.1 mrg 96 1.1 mrg static StackTrace GetStackTraceFromId(u32 id) { 97 1.1 mrg CHECK(id); 98 1.1 mrg StackTrace res = StackDepotGet(id); 99 1.1 mrg CHECK(res.trace); 100 1.1 mrg return res; 101 1.1 mrg } 102 1.1 mrg 103 1.1.1.2 mrg static void MaybePrintAndroidHelpUrl() { 104 1.1.1.2 mrg #if SANITIZER_ANDROID 105 1.1.1.2 mrg Printf( 106 1.1.1.2 mrg "Learn more about HWASan reports: " 107 1.1.1.2 mrg "https://source.android.com/docs/security/test/memory-safety/" 108 1.1.1.2 mrg "hwasan-reports\n"); 109 1.1.1.2 mrg #endif 110 1.1.1.2 mrg } 111 1.1.1.2 mrg 112 1.1.1.2 mrg namespace { 113 1.1 mrg // A RAII object that holds a copy of the current thread stack ring buffer. 114 1.1 mrg // The actual stack buffer may change while we are iterating over it (for 115 1.1 mrg // example, Printf may call syslog() which can itself be built with hwasan). 116 1.1 mrg class SavedStackAllocations { 117 1.1 mrg public: 118 1.1.1.2 mrg SavedStackAllocations() = default; 119 1.1.1.2 mrg 120 1.1.1.2 mrg explicit SavedStackAllocations(Thread *t) { CopyFrom(t); } 121 1.1.1.2 mrg 122 1.1.1.2 mrg void CopyFrom(Thread *t) { 123 1.1.1.2 mrg StackAllocationsRingBuffer *rb = t->stack_allocations(); 124 1.1 mrg uptr size = rb->size() * sizeof(uptr); 125 1.1 mrg void *storage = 126 1.1 mrg MmapAlignedOrDieOnFatalError(size, size * 2, "saved stack allocations"); 127 1.1 mrg new (&rb_) StackAllocationsRingBuffer(*rb, storage); 128 1.1.1.2 mrg thread_id_ = t->unique_id(); 129 1.1 mrg } 130 1.1 mrg 131 1.1 mrg ~SavedStackAllocations() { 132 1.1.1.2 mrg if (rb_) { 133 1.1.1.2 mrg StackAllocationsRingBuffer *rb = get(); 134 1.1.1.2 mrg UnmapOrDie(rb->StartOfStorage(), rb->size() * sizeof(uptr)); 135 1.1.1.2 mrg } 136 1.1.1.2 mrg } 137 1.1.1.2 mrg 138 1.1.1.2 mrg const StackAllocationsRingBuffer *get() const { 139 1.1.1.2 mrg return (const StackAllocationsRingBuffer *)&rb_; 140 1.1 mrg } 141 1.1 mrg 142 1.1 mrg StackAllocationsRingBuffer *get() { 143 1.1 mrg return (StackAllocationsRingBuffer *)&rb_; 144 1.1 mrg } 145 1.1 mrg 146 1.1.1.2 mrg u32 thread_id() const { return thread_id_; } 147 1.1.1.2 mrg 148 1.1 mrg private: 149 1.1.1.2 mrg uptr rb_ = 0; 150 1.1.1.2 mrg u32 thread_id_; 151 1.1 mrg }; 152 1.1 mrg 153 1.1 mrg class Decorator: public __sanitizer::SanitizerCommonDecorator { 154 1.1 mrg public: 155 1.1 mrg Decorator() : SanitizerCommonDecorator() { } 156 1.1 mrg const char *Access() { return Blue(); } 157 1.1 mrg const char *Allocation() const { return Magenta(); } 158 1.1 mrg const char *Origin() const { return Magenta(); } 159 1.1 mrg const char *Name() const { return Green(); } 160 1.1 mrg const char *Location() { return Green(); } 161 1.1 mrg const char *Thread() { return Green(); } 162 1.1 mrg }; 163 1.1.1.2 mrg } // namespace 164 1.1 mrg 165 1.1 mrg static bool FindHeapAllocation(HeapAllocationsRingBuffer *rb, uptr tagged_addr, 166 1.1 mrg HeapAllocationRecord *har, uptr *ring_index, 167 1.1 mrg uptr *num_matching_addrs, 168 1.1 mrg uptr *num_matching_addrs_4b) { 169 1.1 mrg if (!rb) return false; 170 1.1 mrg 171 1.1 mrg *num_matching_addrs = 0; 172 1.1 mrg *num_matching_addrs_4b = 0; 173 1.1 mrg for (uptr i = 0, size = rb->size(); i < size; i++) { 174 1.1 mrg auto h = (*rb)[i]; 175 1.1 mrg if (h.tagged_addr <= tagged_addr && 176 1.1 mrg h.tagged_addr + h.requested_size > tagged_addr) { 177 1.1 mrg *har = h; 178 1.1 mrg *ring_index = i; 179 1.1 mrg return true; 180 1.1 mrg } 181 1.1 mrg 182 1.1 mrg // Measure the number of heap ring buffer entries that would have matched 183 1.1 mrg // if we had only one entry per address (e.g. if the ring buffer data was 184 1.1 mrg // stored at the address itself). This will help us tune the allocator 185 1.1 mrg // implementation for MTE. 186 1.1 mrg if (UntagAddr(h.tagged_addr) <= UntagAddr(tagged_addr) && 187 1.1 mrg UntagAddr(h.tagged_addr) + h.requested_size > UntagAddr(tagged_addr)) { 188 1.1 mrg ++*num_matching_addrs; 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg // Measure the number of heap ring buffer entries that would have matched 192 1.1 mrg // if we only had 4 tag bits, which is the case for MTE. 193 1.1 mrg auto untag_4b = [](uptr p) { 194 1.1 mrg return p & ((1ULL << 60) - 1); 195 1.1 mrg }; 196 1.1 mrg if (untag_4b(h.tagged_addr) <= untag_4b(tagged_addr) && 197 1.1 mrg untag_4b(h.tagged_addr) + h.requested_size > untag_4b(tagged_addr)) { 198 1.1 mrg ++*num_matching_addrs_4b; 199 1.1 mrg } 200 1.1 mrg } 201 1.1 mrg return false; 202 1.1 mrg } 203 1.1 mrg 204 1.1.1.2 mrg static void PrintStackAllocations(const StackAllocationsRingBuffer *sa, 205 1.1 mrg tag_t addr_tag, uptr untagged_addr) { 206 1.1 mrg uptr frames = Min((uptr)flags()->stack_history_size, sa->size()); 207 1.1 mrg bool found_local = false; 208 1.1 mrg for (uptr i = 0; i < frames; i++) { 209 1.1 mrg const uptr *record_addr = &(*sa)[i]; 210 1.1 mrg uptr record = *record_addr; 211 1.1 mrg if (!record) 212 1.1 mrg break; 213 1.1 mrg tag_t base_tag = 214 1.1 mrg reinterpret_cast<uptr>(record_addr) >> kRecordAddrBaseTagShift; 215 1.1 mrg uptr fp = (record >> kRecordFPShift) << kRecordFPLShift; 216 1.1 mrg uptr pc_mask = (1ULL << kRecordFPShift) - 1; 217 1.1 mrg uptr pc = record & pc_mask; 218 1.1 mrg FrameInfo frame; 219 1.1 mrg if (Symbolizer::GetOrInit()->SymbolizeFrame(pc, &frame)) { 220 1.1 mrg for (LocalInfo &local : frame.locals) { 221 1.1 mrg if (!local.has_frame_offset || !local.has_size || !local.has_tag_offset) 222 1.1 mrg continue; 223 1.1 mrg tag_t obj_tag = base_tag ^ local.tag_offset; 224 1.1 mrg if (obj_tag != addr_tag) 225 1.1 mrg continue; 226 1.1 mrg // Calculate the offset from the object address to the faulting 227 1.1 mrg // address. Because we only store bits 4-19 of FP (bits 0-3 are 228 1.1 mrg // guaranteed to be zero), the calculation is performed mod 2^20 and may 229 1.1 mrg // harmlessly underflow if the address mod 2^20 is below the object 230 1.1 mrg // address. 231 1.1 mrg uptr obj_offset = 232 1.1 mrg (untagged_addr - fp - local.frame_offset) & (kRecordFPModulus - 1); 233 1.1 mrg if (obj_offset >= local.size) 234 1.1 mrg continue; 235 1.1 mrg if (!found_local) { 236 1.1 mrg Printf("Potentially referenced stack objects:\n"); 237 1.1 mrg found_local = true; 238 1.1 mrg } 239 1.1 mrg Printf(" %s in %s %s:%d\n", local.name, local.function_name, 240 1.1 mrg local.decl_file, local.decl_line); 241 1.1 mrg } 242 1.1 mrg frame.Clear(); 243 1.1 mrg } 244 1.1 mrg } 245 1.1 mrg 246 1.1 mrg if (found_local) 247 1.1 mrg return; 248 1.1 mrg 249 1.1 mrg // We didn't find any locals. Most likely we don't have symbols, so dump 250 1.1 mrg // the information that we have for offline analysis. 251 1.1 mrg InternalScopedString frame_desc; 252 1.1 mrg Printf("Previously allocated frames:\n"); 253 1.1 mrg for (uptr i = 0; i < frames; i++) { 254 1.1 mrg const uptr *record_addr = &(*sa)[i]; 255 1.1 mrg uptr record = *record_addr; 256 1.1 mrg if (!record) 257 1.1 mrg break; 258 1.1 mrg uptr pc_mask = (1ULL << 48) - 1; 259 1.1 mrg uptr pc = record & pc_mask; 260 1.1.1.2 mrg frame_desc.AppendF(" record_addr:0x%zx record:0x%zx", 261 1.1.1.2 mrg reinterpret_cast<uptr>(record_addr), record); 262 1.1 mrg if (SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc)) { 263 1.1.1.2 mrg StackTracePrinter::GetOrInit()->RenderFrame( 264 1.1.1.2 mrg &frame_desc, " %F %L", 0, frame->info.address, &frame->info, 265 1.1.1.2 mrg common_flags()->symbolize_vs_style, 266 1.1.1.2 mrg common_flags()->strip_path_prefix); 267 1.1 mrg frame->ClearAll(); 268 1.1 mrg } 269 1.1 mrg Printf("%s\n", frame_desc.data()); 270 1.1 mrg frame_desc.clear(); 271 1.1 mrg } 272 1.1 mrg } 273 1.1 mrg 274 1.1 mrg // Returns true if tag == *tag_ptr, reading tags from short granules if 275 1.1 mrg // necessary. This may return a false positive if tags 1-15 are used as a 276 1.1 mrg // regular tag rather than a short granule marker. 277 1.1 mrg static bool TagsEqual(tag_t tag, tag_t *tag_ptr) { 278 1.1 mrg if (tag == *tag_ptr) 279 1.1 mrg return true; 280 1.1 mrg if (*tag_ptr == 0 || *tag_ptr > kShadowAlignment - 1) 281 1.1 mrg return false; 282 1.1 mrg uptr mem = ShadowToMem(reinterpret_cast<uptr>(tag_ptr)); 283 1.1 mrg tag_t inline_tag = *reinterpret_cast<tag_t *>(mem + kShadowAlignment - 1); 284 1.1 mrg return tag == inline_tag; 285 1.1 mrg } 286 1.1 mrg 287 1.1 mrg // HWASan globals store the size of the global in the descriptor. In cases where 288 1.1 mrg // we don't have a binary with symbols, we can't grab the size of the global 289 1.1 mrg // from the debug info - but we might be able to retrieve it from the 290 1.1 mrg // descriptor. Returns zero if the lookup failed. 291 1.1 mrg static uptr GetGlobalSizeFromDescriptor(uptr ptr) { 292 1.1 mrg // Find the ELF object that this global resides in. 293 1.1 mrg Dl_info info; 294 1.1 mrg if (dladdr(reinterpret_cast<void *>(ptr), &info) == 0) 295 1.1 mrg return 0; 296 1.1 mrg auto *ehdr = reinterpret_cast<const ElfW(Ehdr) *>(info.dli_fbase); 297 1.1 mrg auto *phdr_begin = reinterpret_cast<const ElfW(Phdr) *>( 298 1.1 mrg reinterpret_cast<const u8 *>(ehdr) + ehdr->e_phoff); 299 1.1 mrg 300 1.1 mrg // Get the load bias. This is normally the same as the dli_fbase address on 301 1.1 mrg // position-independent code, but can be different on non-PIE executables, 302 1.1 mrg // binaries using LLD's partitioning feature, or binaries compiled with a 303 1.1 mrg // linker script. 304 1.1 mrg ElfW(Addr) load_bias = 0; 305 1.1 mrg for (const auto &phdr : 306 1.1 mrg ArrayRef<const ElfW(Phdr)>(phdr_begin, phdr_begin + ehdr->e_phnum)) { 307 1.1 mrg if (phdr.p_type != PT_LOAD || phdr.p_offset != 0) 308 1.1 mrg continue; 309 1.1 mrg load_bias = reinterpret_cast<ElfW(Addr)>(ehdr) - phdr.p_vaddr; 310 1.1 mrg break; 311 1.1 mrg } 312 1.1 mrg 313 1.1 mrg // Walk all globals in this ELF object, looking for the one we're interested 314 1.1 mrg // in. Once we find it, we can stop iterating and return the size of the 315 1.1 mrg // global we're interested in. 316 1.1 mrg for (const hwasan_global &global : 317 1.1 mrg HwasanGlobalsFor(load_bias, phdr_begin, ehdr->e_phnum)) 318 1.1 mrg if (global.addr() <= ptr && ptr < global.addr() + global.size()) 319 1.1 mrg return global.size(); 320 1.1 mrg 321 1.1 mrg return 0; 322 1.1 mrg } 323 1.1 mrg 324 1.1.1.2 mrg void ReportStats() {} 325 1.1.1.2 mrg 326 1.1.1.2 mrg constexpr uptr kDumpWidth = 16; 327 1.1.1.2 mrg constexpr uptr kShadowLines = 17; 328 1.1.1.2 mrg constexpr uptr kShadowDumpSize = kShadowLines * kDumpWidth; 329 1.1.1.2 mrg 330 1.1.1.2 mrg constexpr uptr kShortLines = 3; 331 1.1.1.2 mrg constexpr uptr kShortDumpSize = kShortLines * kDumpWidth; 332 1.1.1.2 mrg constexpr uptr kShortDumpOffset = (kShadowLines - kShortLines) / 2 * kDumpWidth; 333 1.1.1.2 mrg 334 1.1.1.2 mrg static uptr GetPrintTagStart(uptr addr) { 335 1.1.1.2 mrg addr = MemToShadow(addr); 336 1.1.1.2 mrg addr = RoundDownTo(addr, kDumpWidth); 337 1.1.1.2 mrg addr -= kDumpWidth * (kShadowLines / 2); 338 1.1.1.2 mrg return addr; 339 1.1.1.2 mrg } 340 1.1.1.2 mrg 341 1.1.1.2 mrg template <typename PrintTag> 342 1.1.1.2 mrg static void PrintTagInfoAroundAddr(uptr addr, uptr num_rows, 343 1.1.1.2 mrg InternalScopedString &s, 344 1.1.1.2 mrg PrintTag print_tag) { 345 1.1.1.2 mrg uptr center_row_beg = RoundDownTo(addr, kDumpWidth); 346 1.1.1.2 mrg uptr beg_row = center_row_beg - kDumpWidth * (num_rows / 2); 347 1.1.1.2 mrg uptr end_row = center_row_beg + kDumpWidth * ((num_rows + 1) / 2); 348 1.1.1.2 mrg for (uptr row = beg_row; row < end_row; row += kDumpWidth) { 349 1.1.1.2 mrg s.Append(row == center_row_beg ? "=>" : " "); 350 1.1.1.2 mrg s.AppendF("%p:", (void *)ShadowToMem(row)); 351 1.1.1.2 mrg for (uptr i = 0; i < kDumpWidth; i++) { 352 1.1.1.2 mrg s.Append(row + i == addr ? "[" : " "); 353 1.1.1.2 mrg print_tag(s, row + i); 354 1.1.1.2 mrg s.Append(row + i == addr ? "]" : " "); 355 1.1.1.2 mrg } 356 1.1.1.2 mrg s.AppendF("\n"); 357 1.1.1.2 mrg } 358 1.1.1.2 mrg } 359 1.1.1.2 mrg 360 1.1.1.2 mrg template <typename GetTag, typename GetShortTag> 361 1.1.1.2 mrg static void PrintTagsAroundAddr(uptr addr, GetTag get_tag, 362 1.1.1.2 mrg GetShortTag get_short_tag) { 363 1.1.1.2 mrg InternalScopedString s; 364 1.1.1.2 mrg addr = MemToShadow(addr); 365 1.1.1.2 mrg s.AppendF( 366 1.1.1.2 mrg "Memory tags around the buggy address (one tag corresponds to %zd " 367 1.1.1.2 mrg "bytes):\n", 368 1.1.1.2 mrg kShadowAlignment); 369 1.1.1.2 mrg PrintTagInfoAroundAddr(addr, kShadowLines, s, 370 1.1.1.2 mrg [&](InternalScopedString &s, uptr tag_addr) { 371 1.1.1.2 mrg tag_t tag = get_tag(tag_addr); 372 1.1.1.2 mrg s.AppendF("%02x", tag); 373 1.1.1.2 mrg }); 374 1.1.1.2 mrg 375 1.1.1.2 mrg s.AppendF( 376 1.1.1.2 mrg "Tags for short granules around the buggy address (one tag corresponds " 377 1.1.1.2 mrg "to %zd bytes):\n", 378 1.1.1.2 mrg kShadowAlignment); 379 1.1.1.2 mrg PrintTagInfoAroundAddr(addr, kShortLines, s, 380 1.1.1.2 mrg [&](InternalScopedString &s, uptr tag_addr) { 381 1.1.1.2 mrg tag_t tag = get_tag(tag_addr); 382 1.1.1.2 mrg if (tag >= 1 && tag <= kShadowAlignment) { 383 1.1.1.2 mrg tag_t short_tag = get_short_tag(tag_addr); 384 1.1.1.2 mrg s.AppendF("%02x", short_tag); 385 1.1.1.2 mrg } else { 386 1.1.1.2 mrg s.AppendF(".."); 387 1.1.1.2 mrg } 388 1.1.1.2 mrg }); 389 1.1.1.2 mrg s.AppendF( 390 1.1.1.2 mrg "See " 391 1.1.1.2 mrg "https://clang.llvm.org/docs/" 392 1.1.1.2 mrg "HardwareAssistedAddressSanitizerDesign.html#short-granules for a " 393 1.1.1.2 mrg "description of short granule tags\n"); 394 1.1.1.2 mrg Printf("%s", s.data()); 395 1.1.1.2 mrg } 396 1.1.1.2 mrg 397 1.1.1.2 mrg static uptr GetTopPc(const StackTrace *stack) { 398 1.1.1.2 mrg return stack->size ? StackTrace::GetPreviousInstructionPc(stack->trace[0]) 399 1.1.1.2 mrg : 0; 400 1.1.1.2 mrg } 401 1.1.1.2 mrg 402 1.1.1.2 mrg namespace { 403 1.1.1.2 mrg class BaseReport { 404 1.1.1.2 mrg public: 405 1.1.1.2 mrg BaseReport(StackTrace *stack, bool fatal, uptr tagged_addr, uptr access_size) 406 1.1.1.2 mrg : scoped_report(fatal), 407 1.1.1.2 mrg stack(stack), 408 1.1.1.2 mrg tagged_addr(tagged_addr), 409 1.1.1.2 mrg access_size(access_size), 410 1.1.1.2 mrg untagged_addr(UntagAddr(tagged_addr)), 411 1.1.1.2 mrg ptr_tag(GetTagFromPointer(tagged_addr)), 412 1.1.1.2 mrg mismatch_offset(FindMismatchOffset()), 413 1.1.1.2 mrg heap(CopyHeapChunk()), 414 1.1.1.2 mrg allocations(CopyAllocations()), 415 1.1.1.2 mrg candidate(FindBufferOverflowCandidate()), 416 1.1.1.2 mrg shadow(CopyShadow()) {} 417 1.1.1.2 mrg 418 1.1.1.2 mrg protected: 419 1.1.1.2 mrg struct OverflowCandidate { 420 1.1.1.2 mrg uptr untagged_addr = 0; 421 1.1.1.2 mrg bool after = false; 422 1.1.1.2 mrg bool is_close = false; 423 1.1.1.2 mrg 424 1.1.1.2 mrg struct { 425 1.1.1.2 mrg uptr begin = 0; 426 1.1.1.2 mrg uptr end = 0; 427 1.1.1.2 mrg u32 thread_id = 0; 428 1.1.1.2 mrg u32 stack_id = 0; 429 1.1.1.2 mrg bool is_allocated = false; 430 1.1.1.2 mrg } heap; 431 1.1.1.2 mrg }; 432 1.1.1.2 mrg 433 1.1.1.2 mrg struct HeapAllocation { 434 1.1.1.2 mrg HeapAllocationRecord har = {}; 435 1.1.1.2 mrg uptr ring_index = 0; 436 1.1.1.2 mrg uptr num_matching_addrs = 0; 437 1.1.1.2 mrg uptr num_matching_addrs_4b = 0; 438 1.1.1.2 mrg u32 free_thread_id = 0; 439 1.1.1.2 mrg }; 440 1.1.1.2 mrg 441 1.1.1.2 mrg struct Allocations { 442 1.1.1.2 mrg ArrayRef<SavedStackAllocations> stack; 443 1.1.1.2 mrg ArrayRef<HeapAllocation> heap; 444 1.1.1.2 mrg }; 445 1.1.1.2 mrg 446 1.1.1.2 mrg struct HeapChunk { 447 1.1.1.2 mrg uptr begin = 0; 448 1.1.1.2 mrg uptr size = 0; 449 1.1.1.2 mrg u32 stack_id = 0; 450 1.1.1.2 mrg bool from_small_heap = false; 451 1.1.1.2 mrg bool is_allocated = false; 452 1.1.1.2 mrg }; 453 1.1.1.2 mrg 454 1.1.1.2 mrg struct Shadow { 455 1.1.1.2 mrg uptr addr = 0; 456 1.1.1.2 mrg tag_t tags[kShadowDumpSize] = {}; 457 1.1.1.2 mrg tag_t short_tags[kShortDumpSize] = {}; 458 1.1.1.2 mrg }; 459 1.1.1.2 mrg 460 1.1.1.2 mrg sptr FindMismatchOffset() const; 461 1.1.1.2 mrg Shadow CopyShadow() const; 462 1.1.1.2 mrg tag_t GetTagCopy(uptr addr) const; 463 1.1.1.2 mrg tag_t GetShortTagCopy(uptr addr) const; 464 1.1.1.2 mrg HeapChunk CopyHeapChunk() const; 465 1.1.1.2 mrg Allocations CopyAllocations(); 466 1.1.1.2 mrg OverflowCandidate FindBufferOverflowCandidate() const; 467 1.1.1.2 mrg void PrintAddressDescription() const; 468 1.1.1.2 mrg void PrintHeapOrGlobalCandidate() const; 469 1.1.1.2 mrg void PrintTags(uptr addr) const; 470 1.1.1.2 mrg 471 1.1.1.2 mrg SavedStackAllocations stack_allocations_storage[16]; 472 1.1.1.2 mrg HeapAllocation heap_allocations_storage[256]; 473 1.1.1.2 mrg 474 1.1.1.2 mrg const ScopedReport scoped_report; 475 1.1.1.2 mrg const StackTrace *stack = nullptr; 476 1.1.1.2 mrg const uptr tagged_addr = 0; 477 1.1.1.2 mrg const uptr access_size = 0; 478 1.1.1.2 mrg const uptr untagged_addr = 0; 479 1.1.1.2 mrg const tag_t ptr_tag = 0; 480 1.1.1.2 mrg const sptr mismatch_offset = 0; 481 1.1.1.2 mrg 482 1.1.1.2 mrg const HeapChunk heap; 483 1.1.1.2 mrg const Allocations allocations; 484 1.1.1.2 mrg const OverflowCandidate candidate; 485 1.1.1.2 mrg 486 1.1.1.2 mrg const Shadow shadow; 487 1.1.1.2 mrg }; 488 1.1.1.2 mrg 489 1.1.1.2 mrg sptr BaseReport::FindMismatchOffset() const { 490 1.1.1.2 mrg if (!access_size) 491 1.1.1.2 mrg return 0; 492 1.1.1.2 mrg sptr offset = 493 1.1.1.2 mrg __hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size); 494 1.1.1.2 mrg CHECK_GE(offset, 0); 495 1.1.1.2 mrg CHECK_LT(offset, static_cast<sptr>(access_size)); 496 1.1.1.2 mrg tag_t *tag_ptr = 497 1.1.1.2 mrg reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset)); 498 1.1.1.2 mrg tag_t mem_tag = *tag_ptr; 499 1.1.1.2 mrg 500 1.1.1.2 mrg if (mem_tag && mem_tag < kShadowAlignment) { 501 1.1.1.2 mrg tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) & 502 1.1.1.2 mrg ~(kShadowAlignment - 1)); 503 1.1.1.2 mrg // If offset is 0, (untagged_addr + offset) is not aligned to granules. 504 1.1.1.2 mrg // This is the offset of the leftmost accessed byte within the bad granule. 505 1.1.1.2 mrg u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1); 506 1.1.1.2 mrg tag_t short_tag = granule_ptr[kShadowAlignment - 1]; 507 1.1.1.2 mrg // The first mismatch was a short granule that matched the ptr_tag. 508 1.1.1.2 mrg if (short_tag == ptr_tag) { 509 1.1.1.2 mrg // If the access starts after the end of the short granule, then the first 510 1.1.1.2 mrg // bad byte is the first byte of the access; otherwise it is the first 511 1.1.1.2 mrg // byte past the end of the short granule 512 1.1.1.2 mrg if (mem_tag > in_granule_offset) { 513 1.1.1.2 mrg offset += mem_tag - in_granule_offset; 514 1.1.1.2 mrg } 515 1.1.1.2 mrg } 516 1.1.1.2 mrg } 517 1.1.1.2 mrg return offset; 518 1.1.1.2 mrg } 519 1.1.1.2 mrg 520 1.1.1.2 mrg BaseReport::Shadow BaseReport::CopyShadow() const { 521 1.1.1.2 mrg Shadow result; 522 1.1.1.2 mrg if (!MemIsApp(untagged_addr)) 523 1.1.1.2 mrg return result; 524 1.1.1.2 mrg 525 1.1.1.2 mrg result.addr = GetPrintTagStart(untagged_addr + mismatch_offset); 526 1.1.1.2 mrg uptr tag_addr = result.addr; 527 1.1.1.2 mrg uptr short_end = kShortDumpOffset + ARRAY_SIZE(shadow.short_tags); 528 1.1.1.2 mrg for (uptr i = 0; i < ARRAY_SIZE(result.tags); ++i, ++tag_addr) { 529 1.1.1.2 mrg if (!MemIsShadow(tag_addr)) 530 1.1.1.2 mrg continue; 531 1.1.1.2 mrg result.tags[i] = *reinterpret_cast<tag_t *>(tag_addr); 532 1.1.1.2 mrg if (i < kShortDumpOffset || i >= short_end) 533 1.1.1.2 mrg continue; 534 1.1.1.2 mrg uptr granule_addr = ShadowToMem(tag_addr); 535 1.1.1.2 mrg if (1 <= result.tags[i] && result.tags[i] <= kShadowAlignment && 536 1.1.1.2 mrg IsAccessibleMemoryRange(granule_addr, kShadowAlignment)) { 537 1.1.1.2 mrg result.short_tags[i - kShortDumpOffset] = 538 1.1.1.2 mrg *reinterpret_cast<tag_t *>(granule_addr + kShadowAlignment - 1); 539 1.1.1.2 mrg } 540 1.1.1.2 mrg } 541 1.1.1.2 mrg return result; 542 1.1.1.2 mrg } 543 1.1.1.2 mrg 544 1.1.1.2 mrg tag_t BaseReport::GetTagCopy(uptr addr) const { 545 1.1.1.2 mrg CHECK_GE(addr, shadow.addr); 546 1.1.1.2 mrg uptr idx = addr - shadow.addr; 547 1.1.1.2 mrg CHECK_LT(idx, ARRAY_SIZE(shadow.tags)); 548 1.1.1.2 mrg return shadow.tags[idx]; 549 1.1.1.2 mrg } 550 1.1.1.2 mrg 551 1.1.1.2 mrg tag_t BaseReport::GetShortTagCopy(uptr addr) const { 552 1.1.1.2 mrg CHECK_GE(addr, shadow.addr + kShortDumpOffset); 553 1.1.1.2 mrg uptr idx = addr - shadow.addr - kShortDumpOffset; 554 1.1.1.2 mrg CHECK_LT(idx, ARRAY_SIZE(shadow.short_tags)); 555 1.1.1.2 mrg return shadow.short_tags[idx]; 556 1.1.1.2 mrg } 557 1.1.1.2 mrg 558 1.1.1.2 mrg BaseReport::HeapChunk BaseReport::CopyHeapChunk() const { 559 1.1.1.2 mrg HeapChunk result = {}; 560 1.1.1.2 mrg if (MemIsShadow(untagged_addr)) 561 1.1.1.2 mrg return result; 562 1.1.1.2 mrg HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr); 563 1.1.1.2 mrg result.begin = chunk.Beg(); 564 1.1.1.2 mrg if (result.begin) { 565 1.1.1.2 mrg result.size = chunk.ActualSize(); 566 1.1.1.2 mrg result.from_small_heap = chunk.FromSmallHeap(); 567 1.1.1.2 mrg result.is_allocated = chunk.IsAllocated(); 568 1.1.1.2 mrg result.stack_id = chunk.GetAllocStackId(); 569 1.1.1.2 mrg } 570 1.1.1.2 mrg return result; 571 1.1.1.2 mrg } 572 1.1.1.2 mrg 573 1.1.1.2 mrg BaseReport::Allocations BaseReport::CopyAllocations() { 574 1.1.1.2 mrg if (MemIsShadow(untagged_addr)) 575 1.1.1.2 mrg return {}; 576 1.1.1.2 mrg uptr stack_allocations_count = 0; 577 1.1.1.2 mrg uptr heap_allocations_count = 0; 578 1.1.1.2 mrg hwasanThreadList().VisitAllLiveThreads([&](Thread *t) { 579 1.1.1.2 mrg if (stack_allocations_count < ARRAY_SIZE(stack_allocations_storage) && 580 1.1.1.2 mrg t->AddrIsInStack(untagged_addr)) { 581 1.1.1.2 mrg stack_allocations_storage[stack_allocations_count++].CopyFrom(t); 582 1.1.1.2 mrg } 583 1.1.1.2 mrg 584 1.1.1.2 mrg if (heap_allocations_count < ARRAY_SIZE(heap_allocations_storage)) { 585 1.1.1.2 mrg // Scan all threads' ring buffers to find if it's a heap-use-after-free. 586 1.1.1.2 mrg HeapAllocationRecord har; 587 1.1.1.2 mrg uptr ring_index, num_matching_addrs, num_matching_addrs_4b; 588 1.1.1.2 mrg if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har, 589 1.1.1.2 mrg &ring_index, &num_matching_addrs, 590 1.1.1.2 mrg &num_matching_addrs_4b)) { 591 1.1.1.2 mrg auto &ha = heap_allocations_storage[heap_allocations_count++]; 592 1.1.1.2 mrg ha.har = har; 593 1.1.1.2 mrg ha.ring_index = ring_index; 594 1.1.1.2 mrg ha.num_matching_addrs = num_matching_addrs; 595 1.1.1.2 mrg ha.num_matching_addrs_4b = num_matching_addrs_4b; 596 1.1.1.2 mrg ha.free_thread_id = t->unique_id(); 597 1.1.1.2 mrg } 598 1.1.1.2 mrg } 599 1.1.1.2 mrg }); 600 1.1.1.2 mrg 601 1.1.1.2 mrg return {{stack_allocations_storage, stack_allocations_count}, 602 1.1.1.2 mrg {heap_allocations_storage, heap_allocations_count}}; 603 1.1.1.2 mrg } 604 1.1.1.2 mrg 605 1.1.1.2 mrg BaseReport::OverflowCandidate BaseReport::FindBufferOverflowCandidate() const { 606 1.1.1.2 mrg OverflowCandidate result = {}; 607 1.1.1.2 mrg if (MemIsShadow(untagged_addr)) 608 1.1.1.2 mrg return result; 609 1.1.1.2 mrg // Check if this looks like a heap buffer overflow by scanning 610 1.1.1.2 mrg // the shadow left and right and looking for the first adjacent 611 1.1.1.2 mrg // object with a different memory tag. If that tag matches ptr_tag, 612 1.1.1.2 mrg // check the allocator if it has a live chunk there. 613 1.1.1.2 mrg tag_t *tag_ptr = reinterpret_cast<tag_t *>(MemToShadow(untagged_addr)); 614 1.1.1.2 mrg tag_t *candidate_tag_ptr = nullptr, *left = tag_ptr, *right = tag_ptr; 615 1.1.1.2 mrg uptr candidate_distance = 0; 616 1.1.1.2 mrg for (; candidate_distance < 1000; candidate_distance++) { 617 1.1.1.2 mrg if (MemIsShadow(reinterpret_cast<uptr>(left)) && TagsEqual(ptr_tag, left)) { 618 1.1.1.2 mrg candidate_tag_ptr = left; 619 1.1.1.2 mrg break; 620 1.1.1.2 mrg } 621 1.1.1.2 mrg --left; 622 1.1.1.2 mrg if (MemIsShadow(reinterpret_cast<uptr>(right)) && 623 1.1.1.2 mrg TagsEqual(ptr_tag, right)) { 624 1.1.1.2 mrg candidate_tag_ptr = right; 625 1.1.1.2 mrg break; 626 1.1.1.2 mrg } 627 1.1.1.2 mrg ++right; 628 1.1.1.2 mrg } 629 1.1.1.2 mrg 630 1.1.1.2 mrg constexpr auto kCloseCandidateDistance = 1; 631 1.1.1.2 mrg result.is_close = candidate_distance <= kCloseCandidateDistance; 632 1.1.1.2 mrg 633 1.1.1.2 mrg result.after = candidate_tag_ptr == left; 634 1.1.1.2 mrg result.untagged_addr = ShadowToMem(reinterpret_cast<uptr>(candidate_tag_ptr)); 635 1.1.1.2 mrg HwasanChunkView chunk = FindHeapChunkByAddress(result.untagged_addr); 636 1.1 mrg if (chunk.IsAllocated()) { 637 1.1.1.2 mrg result.heap.is_allocated = true; 638 1.1.1.2 mrg result.heap.begin = chunk.Beg(); 639 1.1.1.2 mrg result.heap.end = chunk.End(); 640 1.1.1.2 mrg result.heap.thread_id = chunk.GetAllocThreadId(); 641 1.1.1.2 mrg result.heap.stack_id = chunk.GetAllocStackId(); 642 1.1.1.2 mrg } 643 1.1.1.2 mrg return result; 644 1.1.1.2 mrg } 645 1.1.1.2 mrg 646 1.1.1.2 mrg void BaseReport::PrintHeapOrGlobalCandidate() const { 647 1.1.1.2 mrg Decorator d; 648 1.1.1.2 mrg if (candidate.heap.is_allocated) { 649 1.1 mrg uptr offset; 650 1.1 mrg const char *whence; 651 1.1.1.2 mrg if (candidate.heap.begin <= untagged_addr && 652 1.1.1.2 mrg untagged_addr < candidate.heap.end) { 653 1.1.1.2 mrg offset = untagged_addr - candidate.heap.begin; 654 1.1 mrg whence = "inside"; 655 1.1.1.2 mrg } else if (candidate.after) { 656 1.1.1.2 mrg offset = untagged_addr - candidate.heap.end; 657 1.1.1.2 mrg whence = "after"; 658 1.1 mrg } else { 659 1.1.1.2 mrg offset = candidate.heap.begin - untagged_addr; 660 1.1.1.2 mrg whence = "before"; 661 1.1 mrg } 662 1.1 mrg Printf("%s", d.Error()); 663 1.1 mrg Printf("\nCause: heap-buffer-overflow\n"); 664 1.1 mrg Printf("%s", d.Default()); 665 1.1 mrg Printf("%s", d.Location()); 666 1.1.1.2 mrg Printf("%p is located %zd bytes %s a %zd-byte region [%p,%p)\n", 667 1.1.1.2 mrg untagged_addr, offset, whence, 668 1.1.1.2 mrg candidate.heap.end - candidate.heap.begin, candidate.heap.begin, 669 1.1.1.2 mrg candidate.heap.end); 670 1.1 mrg Printf("%s", d.Allocation()); 671 1.1.1.2 mrg Printf("allocated by thread T%u here:\n", candidate.heap.thread_id); 672 1.1 mrg Printf("%s", d.Default()); 673 1.1.1.2 mrg GetStackTraceFromId(candidate.heap.stack_id).Print(); 674 1.1 mrg return; 675 1.1 mrg } 676 1.1 mrg // Check whether the address points into a loaded library. If so, this is 677 1.1 mrg // most likely a global variable. 678 1.1 mrg const char *module_name; 679 1.1 mrg uptr module_address; 680 1.1 mrg Symbolizer *sym = Symbolizer::GetOrInit(); 681 1.1.1.2 mrg if (sym->GetModuleNameAndOffsetForPC(candidate.untagged_addr, &module_name, 682 1.1.1.2 mrg &module_address)) { 683 1.1 mrg Printf("%s", d.Error()); 684 1.1 mrg Printf("\nCause: global-overflow\n"); 685 1.1 mrg Printf("%s", d.Default()); 686 1.1 mrg DataInfo info; 687 1.1 mrg Printf("%s", d.Location()); 688 1.1.1.2 mrg if (sym->SymbolizeData(candidate.untagged_addr, &info) && info.start) { 689 1.1 mrg Printf( 690 1.1.1.2 mrg "%p is located %zd bytes %s a %zd-byte global variable " 691 1.1 mrg "%s [%p,%p) in %s\n", 692 1.1 mrg untagged_addr, 693 1.1.1.2 mrg candidate.after ? untagged_addr - (info.start + info.size) 694 1.1.1.2 mrg : info.start - untagged_addr, 695 1.1.1.2 mrg candidate.after ? "after" : "before", info.size, info.name, 696 1.1 mrg info.start, info.start + info.size, module_name); 697 1.1 mrg } else { 698 1.1.1.2 mrg uptr size = GetGlobalSizeFromDescriptor(candidate.untagged_addr); 699 1.1 mrg if (size == 0) 700 1.1 mrg // We couldn't find the size of the global from the descriptors. 701 1.1 mrg Printf( 702 1.1.1.2 mrg "%p is located %s a global variable in " 703 1.1 mrg "\n #0 0x%x (%s+0x%x)\n", 704 1.1.1.2 mrg untagged_addr, candidate.after ? "after" : "before", 705 1.1.1.2 mrg candidate.untagged_addr, module_name, module_address); 706 1.1 mrg else 707 1.1 mrg Printf( 708 1.1.1.2 mrg "%p is located %s a %zd-byte global variable in " 709 1.1 mrg "\n #0 0x%x (%s+0x%x)\n", 710 1.1.1.2 mrg untagged_addr, candidate.after ? "after" : "before", size, 711 1.1.1.2 mrg candidate.untagged_addr, module_name, module_address); 712 1.1 mrg } 713 1.1 mrg Printf("%s", d.Default()); 714 1.1 mrg } 715 1.1 mrg } 716 1.1 mrg 717 1.1.1.2 mrg void BaseReport::PrintAddressDescription() const { 718 1.1 mrg Decorator d; 719 1.1 mrg int num_descriptions_printed = 0; 720 1.1 mrg 721 1.1 mrg if (MemIsShadow(untagged_addr)) { 722 1.1 mrg Printf("%s%p is HWAsan shadow memory.\n%s", d.Location(), untagged_addr, 723 1.1 mrg d.Default()); 724 1.1 mrg return; 725 1.1 mrg } 726 1.1 mrg 727 1.1 mrg // Print some very basic information about the address, if it's a heap. 728 1.1.1.2 mrg if (heap.begin) { 729 1.1.1.2 mrg Printf( 730 1.1.1.2 mrg "%s[%p,%p) is a %s %s heap chunk; " 731 1.1.1.2 mrg "size: %zd offset: %zd\n%s", 732 1.1.1.2 mrg d.Location(), heap.begin, heap.begin + heap.size, 733 1.1.1.2 mrg heap.from_small_heap ? "small" : "large", 734 1.1.1.2 mrg heap.is_allocated ? "allocated" : "unallocated", heap.size, 735 1.1.1.2 mrg untagged_addr - heap.begin, d.Default()); 736 1.1 mrg } 737 1.1 mrg 738 1.1.1.2 mrg auto announce_by_id = [](u32 thread_id) { 739 1.1.1.2 mrg hwasanThreadList().VisitAllLiveThreads([&](Thread *t) { 740 1.1.1.2 mrg if (thread_id == t->unique_id()) 741 1.1.1.2 mrg t->Announce(); 742 1.1.1.2 mrg }); 743 1.1.1.2 mrg }; 744 1.1 mrg 745 1.1 mrg // Check stack first. If the address is on the stack of a live thread, we 746 1.1 mrg // know it cannot be a heap / global overflow. 747 1.1.1.2 mrg for (const auto &sa : allocations.stack) { 748 1.1.1.2 mrg // TODO(fmayer): figure out how to distinguish use-after-return and 749 1.1.1.2 mrg // stack-buffer-overflow. 750 1.1.1.2 mrg Printf("%s", d.Error()); 751 1.1.1.2 mrg Printf("\nCause: stack tag-mismatch\n"); 752 1.1.1.2 mrg Printf("%s", d.Location()); 753 1.1.1.2 mrg Printf("Address %p is located in stack of thread T%zd\n", untagged_addr, 754 1.1.1.2 mrg sa.thread_id()); 755 1.1.1.2 mrg Printf("%s", d.Default()); 756 1.1.1.2 mrg announce_by_id(sa.thread_id()); 757 1.1.1.2 mrg PrintStackAllocations(sa.get(), ptr_tag, untagged_addr); 758 1.1.1.2 mrg num_descriptions_printed++; 759 1.1 mrg } 760 1.1 mrg 761 1.1.1.2 mrg if (allocations.stack.empty() && candidate.untagged_addr && 762 1.1.1.2 mrg candidate.is_close) { 763 1.1.1.2 mrg PrintHeapOrGlobalCandidate(); 764 1.1 mrg num_descriptions_printed++; 765 1.1 mrg } 766 1.1 mrg 767 1.1.1.2 mrg for (const auto &ha : allocations.heap) { 768 1.1.1.2 mrg const HeapAllocationRecord har = ha.har; 769 1.1 mrg 770 1.1.1.2 mrg Printf("%s", d.Error()); 771 1.1.1.2 mrg Printf("\nCause: use-after-free\n"); 772 1.1.1.2 mrg Printf("%s", d.Location()); 773 1.1.1.2 mrg Printf("%p is located %zd bytes inside a %zd-byte region [%p,%p)\n", 774 1.1.1.2 mrg untagged_addr, untagged_addr - UntagAddr(har.tagged_addr), 775 1.1.1.2 mrg har.requested_size, UntagAddr(har.tagged_addr), 776 1.1.1.2 mrg UntagAddr(har.tagged_addr) + har.requested_size); 777 1.1.1.2 mrg Printf("%s", d.Allocation()); 778 1.1.1.2 mrg Printf("freed by thread T%u here:\n", ha.free_thread_id); 779 1.1.1.2 mrg Printf("%s", d.Default()); 780 1.1.1.2 mrg GetStackTraceFromId(har.free_context_id).Print(); 781 1.1.1.2 mrg 782 1.1.1.2 mrg Printf("%s", d.Allocation()); 783 1.1.1.2 mrg Printf("previously allocated by thread T%u here:\n", har.alloc_thread_id); 784 1.1.1.2 mrg Printf("%s", d.Default()); 785 1.1.1.2 mrg GetStackTraceFromId(har.alloc_context_id).Print(); 786 1.1.1.2 mrg 787 1.1.1.2 mrg // Print a developer note: the index of this heap object 788 1.1.1.2 mrg // in the thread's deallocation ring buffer. 789 1.1.1.2 mrg Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", ha.ring_index + 1, 790 1.1.1.2 mrg flags()->heap_history_size); 791 1.1.1.2 mrg Printf("hwasan_dev_note_num_matching_addrs: %zd\n", ha.num_matching_addrs); 792 1.1.1.2 mrg Printf("hwasan_dev_note_num_matching_addrs_4b: %zd\n", 793 1.1.1.2 mrg ha.num_matching_addrs_4b); 794 1.1.1.2 mrg 795 1.1.1.2 mrg announce_by_id(ha.free_thread_id); 796 1.1.1.2 mrg // TODO: announce_by_id(har.alloc_thread_id); 797 1.1.1.2 mrg num_descriptions_printed++; 798 1.1.1.2 mrg } 799 1.1 mrg 800 1.1.1.2 mrg if (candidate.untagged_addr && num_descriptions_printed == 0) { 801 1.1.1.2 mrg PrintHeapOrGlobalCandidate(); 802 1.1 mrg num_descriptions_printed++; 803 1.1 mrg } 804 1.1 mrg 805 1.1 mrg // Print the remaining threads, as an extra information, 1 line per thread. 806 1.1.1.2 mrg if (flags()->print_live_threads_info) 807 1.1.1.2 mrg hwasanThreadList().VisitAllLiveThreads([&](Thread *t) { t->Announce(); }); 808 1.1 mrg 809 1.1 mrg if (!num_descriptions_printed) 810 1.1 mrg // We exhausted our possibilities. Bail out. 811 1.1 mrg Printf("HWAddressSanitizer can not describe address in more detail.\n"); 812 1.1 mrg if (num_descriptions_printed > 1) { 813 1.1 mrg Printf( 814 1.1 mrg "There are %d potential causes, printed above in order " 815 1.1 mrg "of likeliness.\n", 816 1.1 mrg num_descriptions_printed); 817 1.1 mrg } 818 1.1 mrg } 819 1.1 mrg 820 1.1.1.2 mrg void BaseReport::PrintTags(uptr addr) const { 821 1.1.1.2 mrg if (shadow.addr) { 822 1.1.1.2 mrg PrintTagsAroundAddr( 823 1.1.1.2 mrg addr, [&](uptr addr) { return GetTagCopy(addr); }, 824 1.1.1.2 mrg [&](uptr addr) { return GetShortTagCopy(addr); }); 825 1.1 mrg } 826 1.1 mrg } 827 1.1 mrg 828 1.1.1.2 mrg class InvalidFreeReport : public BaseReport { 829 1.1.1.2 mrg public: 830 1.1.1.2 mrg InvalidFreeReport(StackTrace *stack, uptr tagged_addr) 831 1.1.1.2 mrg : BaseReport(stack, flags()->halt_on_error, tagged_addr, 0) {} 832 1.1.1.2 mrg ~InvalidFreeReport(); 833 1.1 mrg 834 1.1.1.2 mrg private: 835 1.1.1.2 mrg }; 836 1.1 mrg 837 1.1.1.2 mrg InvalidFreeReport::~InvalidFreeReport() { 838 1.1 mrg Decorator d; 839 1.1 mrg Printf("%s", d.Error()); 840 1.1 mrg uptr pc = GetTopPc(stack); 841 1.1 mrg const char *bug_type = "invalid-free"; 842 1.1 mrg const Thread *thread = GetCurrentThread(); 843 1.1 mrg if (thread) { 844 1.1 mrg Report("ERROR: %s: %s on address %p at pc %p on thread T%zd\n", 845 1.1 mrg SanitizerToolName, bug_type, untagged_addr, pc, thread->unique_id()); 846 1.1 mrg } else { 847 1.1 mrg Report("ERROR: %s: %s on address %p at pc %p on unknown thread\n", 848 1.1 mrg SanitizerToolName, bug_type, untagged_addr, pc); 849 1.1 mrg } 850 1.1 mrg Printf("%s", d.Access()); 851 1.1.1.2 mrg if (shadow.addr) { 852 1.1.1.2 mrg Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, 853 1.1.1.2 mrg GetTagCopy(MemToShadow(untagged_addr))); 854 1.1.1.2 mrg } 855 1.1 mrg Printf("%s", d.Default()); 856 1.1 mrg 857 1.1 mrg stack->Print(); 858 1.1 mrg 859 1.1.1.2 mrg PrintAddressDescription(); 860 1.1.1.2 mrg PrintTags(untagged_addr); 861 1.1.1.2 mrg MaybePrintAndroidHelpUrl(); 862 1.1 mrg ReportErrorSummary(bug_type, stack); 863 1.1 mrg } 864 1.1 mrg 865 1.1.1.2 mrg class TailOverwrittenReport : public BaseReport { 866 1.1.1.2 mrg public: 867 1.1.1.2 mrg explicit TailOverwrittenReport(StackTrace *stack, uptr tagged_addr, 868 1.1.1.2 mrg uptr orig_size, const u8 *expected) 869 1.1.1.2 mrg : BaseReport(stack, flags()->halt_on_error, tagged_addr, 0), 870 1.1.1.2 mrg orig_size(orig_size), 871 1.1.1.2 mrg tail_size(kShadowAlignment - (orig_size % kShadowAlignment)) { 872 1.1.1.2 mrg CHECK_GT(tail_size, 0U); 873 1.1.1.2 mrg CHECK_LT(tail_size, kShadowAlignment); 874 1.1.1.2 mrg internal_memcpy(tail_copy, 875 1.1.1.2 mrg reinterpret_cast<u8 *>(untagged_addr + orig_size), 876 1.1.1.2 mrg tail_size); 877 1.1.1.2 mrg internal_memcpy(actual_expected, expected, tail_size); 878 1.1.1.2 mrg // Short granule is stashed in the last byte of the magic string. To avoid 879 1.1.1.2 mrg // confusion, make the expected magic string contain the short granule tag. 880 1.1.1.2 mrg if (orig_size % kShadowAlignment != 0) 881 1.1.1.2 mrg actual_expected[tail_size - 1] = ptr_tag; 882 1.1 mrg } 883 1.1.1.2 mrg ~TailOverwrittenReport(); 884 1.1 mrg 885 1.1.1.2 mrg private: 886 1.1.1.2 mrg const uptr orig_size = 0; 887 1.1.1.2 mrg const uptr tail_size = 0; 888 1.1.1.2 mrg u8 actual_expected[kShadowAlignment] = {}; 889 1.1.1.2 mrg u8 tail_copy[kShadowAlignment] = {}; 890 1.1.1.2 mrg }; 891 1.1.1.2 mrg 892 1.1.1.2 mrg TailOverwrittenReport::~TailOverwrittenReport() { 893 1.1 mrg Decorator d; 894 1.1 mrg Printf("%s", d.Error()); 895 1.1 mrg const char *bug_type = "allocation-tail-overwritten"; 896 1.1 mrg Report("ERROR: %s: %s; heap object [%p,%p) of size %zd\n", SanitizerToolName, 897 1.1 mrg bug_type, untagged_addr, untagged_addr + orig_size, orig_size); 898 1.1 mrg Printf("\n%s", d.Default()); 899 1.1 mrg Printf( 900 1.1 mrg "Stack of invalid access unknown. Issue detected at deallocation " 901 1.1 mrg "time.\n"); 902 1.1 mrg Printf("%s", d.Allocation()); 903 1.1 mrg Printf("deallocated here:\n"); 904 1.1 mrg Printf("%s", d.Default()); 905 1.1 mrg stack->Print(); 906 1.1.1.2 mrg if (heap.begin) { 907 1.1 mrg Printf("%s", d.Allocation()); 908 1.1 mrg Printf("allocated here:\n"); 909 1.1 mrg Printf("%s", d.Default()); 910 1.1.1.2 mrg GetStackTraceFromId(heap.stack_id).Print(); 911 1.1 mrg } 912 1.1 mrg 913 1.1 mrg InternalScopedString s; 914 1.1.1.2 mrg u8 *tail = tail_copy; 915 1.1.1.2 mrg s.AppendF("Tail contains: "); 916 1.1.1.2 mrg for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.AppendF(".. "); 917 1.1.1.2 mrg for (uptr i = 0; i < tail_size; i++) s.AppendF("%02x ", tail[i]); 918 1.1.1.2 mrg s.AppendF("\n"); 919 1.1.1.2 mrg s.AppendF("Expected: "); 920 1.1.1.2 mrg for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.AppendF(".. "); 921 1.1.1.2 mrg for (uptr i = 0; i < tail_size; i++) s.AppendF("%02x ", actual_expected[i]); 922 1.1.1.2 mrg s.AppendF("\n"); 923 1.1.1.2 mrg s.AppendF(" "); 924 1.1.1.2 mrg for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.AppendF(" "); 925 1.1 mrg for (uptr i = 0; i < tail_size; i++) 926 1.1.1.2 mrg s.AppendF("%s ", actual_expected[i] != tail[i] ? "^^" : " "); 927 1.1 mrg 928 1.1.1.2 mrg s.AppendF( 929 1.1.1.2 mrg "\nThis error occurs when a buffer overflow overwrites memory\n" 930 1.1.1.2 mrg "after a heap object, but within the %zd-byte granule, e.g.\n" 931 1.1.1.2 mrg " char *x = new char[20];\n" 932 1.1.1.2 mrg " x[25] = 42;\n" 933 1.1.1.2 mrg "%s does not detect such bugs in uninstrumented code at the time of " 934 1.1.1.2 mrg "write," 935 1.1.1.2 mrg "\nbut can detect them at the time of free/delete.\n" 936 1.1.1.2 mrg "To disable this feature set HWASAN_OPTIONS=free_checks_tail_magic=0\n", 937 1.1.1.2 mrg kShadowAlignment, SanitizerToolName); 938 1.1 mrg Printf("%s", s.data()); 939 1.1 mrg GetCurrentThread()->Announce(); 940 1.1.1.2 mrg PrintTags(untagged_addr); 941 1.1.1.2 mrg MaybePrintAndroidHelpUrl(); 942 1.1 mrg ReportErrorSummary(bug_type, stack); 943 1.1 mrg } 944 1.1 mrg 945 1.1.1.2 mrg class TagMismatchReport : public BaseReport { 946 1.1.1.2 mrg public: 947 1.1.1.2 mrg explicit TagMismatchReport(StackTrace *stack, uptr tagged_addr, 948 1.1.1.2 mrg uptr access_size, bool is_store, bool fatal, 949 1.1.1.2 mrg uptr *registers_frame) 950 1.1.1.2 mrg : BaseReport(stack, fatal, tagged_addr, access_size), 951 1.1.1.2 mrg is_store(is_store), 952 1.1.1.2 mrg registers_frame(registers_frame) {} 953 1.1.1.2 mrg ~TagMismatchReport(); 954 1.1.1.2 mrg 955 1.1.1.2 mrg private: 956 1.1.1.2 mrg const bool is_store; 957 1.1.1.2 mrg const uptr *registers_frame; 958 1.1.1.2 mrg }; 959 1.1 mrg 960 1.1.1.2 mrg TagMismatchReport::~TagMismatchReport() { 961 1.1 mrg Decorator d; 962 1.1 mrg // TODO: when possible, try to print heap-use-after-free, etc. 963 1.1 mrg const char *bug_type = "tag-mismatch"; 964 1.1 mrg uptr pc = GetTopPc(stack); 965 1.1 mrg Printf("%s", d.Error()); 966 1.1 mrg Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type, 967 1.1 mrg untagged_addr, pc); 968 1.1 mrg 969 1.1 mrg Thread *t = GetCurrentThread(); 970 1.1 mrg 971 1.1.1.2 mrg tag_t mem_tag = GetTagCopy(MemToShadow(untagged_addr + mismatch_offset)); 972 1.1 mrg 973 1.1 mrg Printf("%s", d.Access()); 974 1.1 mrg if (mem_tag && mem_tag < kShadowAlignment) { 975 1.1.1.2 mrg tag_t short_tag = 976 1.1.1.2 mrg GetShortTagCopy(MemToShadow(untagged_addr + mismatch_offset)); 977 1.1 mrg Printf( 978 1.1 mrg "%s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n", 979 1.1 mrg is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag, 980 1.1 mrg mem_tag, short_tag, t->unique_id()); 981 1.1 mrg } else { 982 1.1 mrg Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n", 983 1.1 mrg is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag, 984 1.1 mrg mem_tag, t->unique_id()); 985 1.1 mrg } 986 1.1.1.2 mrg if (mismatch_offset) 987 1.1.1.2 mrg Printf("Invalid access starting at offset %zu\n", mismatch_offset); 988 1.1 mrg Printf("%s", d.Default()); 989 1.1 mrg 990 1.1 mrg stack->Print(); 991 1.1 mrg 992 1.1.1.2 mrg PrintAddressDescription(); 993 1.1 mrg t->Announce(); 994 1.1 mrg 995 1.1.1.2 mrg PrintTags(untagged_addr + mismatch_offset); 996 1.1 mrg 997 1.1 mrg if (registers_frame) 998 1.1 mrg ReportRegisters(registers_frame, pc); 999 1.1 mrg 1000 1.1.1.2 mrg MaybePrintAndroidHelpUrl(); 1001 1.1 mrg ReportErrorSummary(bug_type, stack); 1002 1.1 mrg } 1003 1.1.1.2 mrg } // namespace 1004 1.1.1.2 mrg 1005 1.1.1.2 mrg void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) { 1006 1.1.1.2 mrg InvalidFreeReport R(stack, tagged_addr); 1007 1.1.1.2 mrg } 1008 1.1.1.2 mrg 1009 1.1.1.2 mrg void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size, 1010 1.1.1.2 mrg const u8 *expected) { 1011 1.1.1.2 mrg TailOverwrittenReport R(stack, tagged_addr, orig_size, expected); 1012 1.1.1.2 mrg } 1013 1.1.1.2 mrg 1014 1.1.1.2 mrg void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size, 1015 1.1.1.2 mrg bool is_store, bool fatal, uptr *registers_frame) { 1016 1.1.1.2 mrg TagMismatchReport R(stack, tagged_addr, access_size, is_store, fatal, 1017 1.1.1.2 mrg registers_frame); 1018 1.1.1.2 mrg } 1019 1.1 mrg 1020 1.1 mrg // See the frame breakdown defined in __hwasan_tag_mismatch (from 1021 1.1.1.2 mrg // hwasan_tag_mismatch_{aarch64,riscv64}.S). 1022 1.1.1.2 mrg void ReportRegisters(const uptr *frame, uptr pc) { 1023 1.1 mrg Printf("Registers where the failure occurred (pc %p):\n", pc); 1024 1.1 mrg 1025 1.1 mrg // We explicitly print a single line (4 registers/line) each iteration to 1026 1.1 mrg // reduce the amount of logcat error messages printed. Each Printf() will 1027 1.1 mrg // result in a new logcat line, irrespective of whether a newline is present, 1028 1.1 mrg // and so we wish to reduce the number of Printf() calls we have to make. 1029 1.1.1.2 mrg #if defined(__aarch64__) 1030 1.1 mrg Printf(" x0 %016llx x1 %016llx x2 %016llx x3 %016llx\n", 1031 1.1 mrg frame[0], frame[1], frame[2], frame[3]); 1032 1.1.1.2 mrg #elif SANITIZER_RISCV64 1033 1.1.1.2 mrg Printf(" sp %016llx x1 %016llx x2 %016llx x3 %016llx\n", 1034 1.1.1.2 mrg reinterpret_cast<const u8 *>(frame) + 256, frame[1], frame[2], 1035 1.1.1.2 mrg frame[3]); 1036 1.1.1.2 mrg #endif 1037 1.1 mrg Printf(" x4 %016llx x5 %016llx x6 %016llx x7 %016llx\n", 1038 1.1 mrg frame[4], frame[5], frame[6], frame[7]); 1039 1.1 mrg Printf(" x8 %016llx x9 %016llx x10 %016llx x11 %016llx\n", 1040 1.1 mrg frame[8], frame[9], frame[10], frame[11]); 1041 1.1 mrg Printf(" x12 %016llx x13 %016llx x14 %016llx x15 %016llx\n", 1042 1.1 mrg frame[12], frame[13], frame[14], frame[15]); 1043 1.1 mrg Printf(" x16 %016llx x17 %016llx x18 %016llx x19 %016llx\n", 1044 1.1 mrg frame[16], frame[17], frame[18], frame[19]); 1045 1.1 mrg Printf(" x20 %016llx x21 %016llx x22 %016llx x23 %016llx\n", 1046 1.1 mrg frame[20], frame[21], frame[22], frame[23]); 1047 1.1 mrg Printf(" x24 %016llx x25 %016llx x26 %016llx x27 %016llx\n", 1048 1.1 mrg frame[24], frame[25], frame[26], frame[27]); 1049 1.1 mrg // hwasan_check* reduces the stack pointer by 256, then __hwasan_tag_mismatch 1050 1.1 mrg // passes it to this function. 1051 1.1.1.2 mrg #if defined(__aarch64__) 1052 1.1 mrg Printf(" x28 %016llx x29 %016llx x30 %016llx sp %016llx\n", frame[28], 1053 1.1.1.2 mrg frame[29], frame[30], reinterpret_cast<const u8 *>(frame) + 256); 1054 1.1.1.2 mrg #elif SANITIZER_RISCV64 1055 1.1.1.2 mrg Printf(" x28 %016llx x29 %016llx x30 %016llx x31 %016llx\n", frame[28], 1056 1.1.1.2 mrg frame[29], frame[30], frame[31]); 1057 1.1.1.2 mrg #else 1058 1.1.1.2 mrg #endif 1059 1.1 mrg } 1060 1.1 mrg 1061 1.1 mrg } // namespace __hwasan 1062 1.1 mrg 1063 1.1 mrg void __hwasan_set_error_report_callback(void (*callback)(const char *)) { 1064 1.1 mrg __hwasan::ScopedReport::SetErrorReportCallback(callback); 1065 1.1 mrg } 1066