]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_report.cc
MFV r323917: 8648 Fix range locking in ZIL commit codepath
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_report.cc
1 //===-- asan_report.cc ----------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // This file contains error reporting code.
13 //===----------------------------------------------------------------------===//
14
15 #include "asan_errors.h"
16 #include "asan_flags.h"
17 #include "asan_descriptions.h"
18 #include "asan_internal.h"
19 #include "asan_mapping.h"
20 #include "asan_report.h"
21 #include "asan_scariness_score.h"
22 #include "asan_stack.h"
23 #include "asan_thread.h"
24 #include "sanitizer_common/sanitizer_common.h"
25 #include "sanitizer_common/sanitizer_flags.h"
26 #include "sanitizer_common/sanitizer_report_decorator.h"
27 #include "sanitizer_common/sanitizer_stackdepot.h"
28 #include "sanitizer_common/sanitizer_symbolizer.h"
29
30 namespace __asan {
31
32 // -------------------- User-specified callbacks ----------------- {{{1
33 static void (*error_report_callback)(const char*);
34 static char *error_message_buffer = nullptr;
35 static uptr error_message_buffer_pos = 0;
36 static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED);
37 static const unsigned kAsanBuggyPcPoolSize = 25;
38 static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
39
40 void AppendToErrorMessageBuffer(const char *buffer) {
41   BlockingMutexLock l(&error_message_buf_mutex);
42   if (!error_message_buffer) {
43     error_message_buffer =
44       (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
45     error_message_buffer_pos = 0;
46   }
47   uptr length = internal_strlen(buffer);
48   RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
49   uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
50   internal_strncpy(error_message_buffer + error_message_buffer_pos,
51                    buffer, remaining);
52   error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
53   // FIXME: reallocate the buffer instead of truncating the message.
54   error_message_buffer_pos += Min(remaining, length);
55 }
56
57 // ---------------------- Helper functions ----------------------- {{{1
58
59 void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
60                      bool in_shadow, const char *after) {
61   Decorator d;
62   str->append("%s%s%x%x%s%s", before,
63               in_shadow ? d.ShadowByte(byte) : d.MemoryByte(),
64               byte >> 4, byte & 15,
65               in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after);
66 }
67
68 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
69                                 const char *zone_name) {
70   if (zone_ptr) {
71     if (zone_name) {
72       Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
73                  ptr, zone_ptr, zone_name);
74     } else {
75       Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
76                  ptr, zone_ptr);
77     }
78   } else {
79     Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
80   }
81 }
82
83 // ---------------------- Address Descriptions ------------------- {{{1
84
85 bool ParseFrameDescription(const char *frame_descr,
86                            InternalMmapVector<StackVarDescr> *vars) {
87   CHECK(frame_descr);
88   char *p;
89   // This string is created by the compiler and has the following form:
90   // "n alloc_1 alloc_2 ... alloc_n"
91   // where alloc_i looks like "offset size len ObjectName"
92   // or                       "offset size len ObjectName:line".
93   uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
94   if (n_objects == 0)
95     return false;
96
97   for (uptr i = 0; i < n_objects; i++) {
98     uptr beg  = (uptr)internal_simple_strtoll(p, &p, 10);
99     uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
100     uptr len  = (uptr)internal_simple_strtoll(p, &p, 10);
101     if (beg == 0 || size == 0 || *p != ' ') {
102       return false;
103     }
104     p++;
105     char *colon_pos = internal_strchr(p, ':');
106     uptr line = 0;
107     uptr name_len = len;
108     if (colon_pos != nullptr && colon_pos < p + len) {
109       name_len = colon_pos - p;
110       line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
111     }
112     StackVarDescr var = {beg, size, p, name_len, line};
113     vars->push_back(var);
114     p += len;
115   }
116
117   return true;
118 }
119
120 // -------------------- Different kinds of reports ----------------- {{{1
121
122 // Use ScopedInErrorReport to run common actions just before and
123 // immediately after printing error report.
124 class ScopedInErrorReport {
125  public:
126   explicit ScopedInErrorReport(bool fatal = false) {
127     halt_on_error_ = fatal || flags()->halt_on_error;
128
129     if (lock_.TryLock()) {
130       StartReporting();
131       return;
132     }
133
134     // ASan found two bugs in different threads simultaneously.
135
136     u32 current_tid = GetCurrentTidOrInvalid();
137     if (reporting_thread_tid_ == current_tid ||
138         reporting_thread_tid_ == kInvalidTid) {
139       // This is either asynch signal or nested error during error reporting.
140       // Fail simple to avoid deadlocks in Report().
141
142       // Can't use Report() here because of potential deadlocks
143       // in nested signal handlers.
144       const char msg[] = "AddressSanitizer: nested bug in the same thread, "
145                          "aborting.\n";
146       WriteToFile(kStderrFd, msg, sizeof(msg));
147
148       internal__exit(common_flags()->exitcode);
149     }
150
151     if (halt_on_error_) {
152       // Do not print more than one report, otherwise they will mix up.
153       // Error reporting functions shouldn't return at this situation, as
154       // they are effectively no-returns.
155
156       Report("AddressSanitizer: while reporting a bug found another one. "
157              "Ignoring.\n");
158
159       // Sleep long enough to make sure that the thread which started
160       // to print an error report will finish doing it.
161       SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
162
163       // If we're still not dead for some reason, use raw _exit() instead of
164       // Die() to bypass any additional checks.
165       internal__exit(common_flags()->exitcode);
166     } else {
167       // The other thread will eventually finish reporting
168       // so it's safe to wait
169       lock_.Lock();
170     }
171
172     StartReporting();
173   }
174
175   ~ScopedInErrorReport() {
176     ASAN_ON_ERROR();
177     if (current_error_.IsValid()) current_error_.Print();
178
179     // Make sure the current thread is announced.
180     DescribeThread(GetCurrentThread());
181     // We may want to grab this lock again when printing stats.
182     asanThreadRegistry().Unlock();
183     // Print memory stats.
184     if (flags()->print_stats)
185       __asan_print_accumulated_stats();
186
187     if (common_flags()->print_cmdline)
188       PrintCmdline();
189
190     if (common_flags()->print_module_map == 2) PrintModuleMap();
191
192     // Copy the message buffer so that we could start logging without holding a
193     // lock that gets aquired during printing.
194     InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
195     {
196       BlockingMutexLock l(&error_message_buf_mutex);
197       internal_memcpy(buffer_copy.data(),
198                       error_message_buffer, kErrorMessageBufferSize);
199     }
200
201     LogFullErrorReport(buffer_copy.data());
202
203     if (error_report_callback) {
204       error_report_callback(buffer_copy.data());
205     }
206
207     if (halt_on_error_ && common_flags()->abort_on_error) {
208       // On Android the message is truncated to 512 characters.
209       // FIXME: implement "compact" error format, possibly without, or with
210       // highly compressed stack traces?
211       // FIXME: or just use the summary line as abort message?
212       SetAbortMessage(buffer_copy.data());
213     }
214
215     // In halt_on_error = false mode, reset the current error object (before
216     // unlocking).
217     if (!halt_on_error_)
218       internal_memset(&current_error_, 0, sizeof(current_error_));
219
220     CommonSanitizerReportMutex.Unlock();
221     reporting_thread_tid_ = kInvalidTid;
222     lock_.Unlock();
223     if (halt_on_error_) {
224       Report("ABORTING\n");
225       Die();
226     }
227   }
228
229   void ReportError(const ErrorDescription &description) {
230     // Can only report one error per ScopedInErrorReport.
231     CHECK_EQ(current_error_.kind, kErrorKindInvalid);
232     current_error_ = description;
233   }
234
235   static ErrorDescription &CurrentError() {
236     return current_error_;
237   }
238
239  private:
240   void StartReporting() {
241     // Make sure the registry and sanitizer report mutexes are locked while
242     // we're printing an error report.
243     // We can lock them only here to avoid self-deadlock in case of
244     // recursive reports.
245     asanThreadRegistry().Lock();
246     CommonSanitizerReportMutex.Lock();
247     reporting_thread_tid_ = GetCurrentTidOrInvalid();
248     Printf("===================================================="
249            "=============\n");
250   }
251
252   static StaticSpinMutex lock_;
253   static u32 reporting_thread_tid_;
254   // Error currently being reported. This enables the destructor to interact
255   // with the debugger and point it to an error description.
256   static ErrorDescription current_error_;
257   bool halt_on_error_;
258 };
259
260 StaticSpinMutex ScopedInErrorReport::lock_;
261 u32 ScopedInErrorReport::reporting_thread_tid_ = kInvalidTid;
262 ErrorDescription ScopedInErrorReport::current_error_;
263
264 void ReportStackOverflow(const SignalContext &sig) {
265   ScopedInErrorReport in_report(/*fatal*/ true);
266   ErrorStackOverflow error(GetCurrentTidOrInvalid(), sig);
267   in_report.ReportError(error);
268 }
269
270 void ReportDeadlySignal(int signo, const SignalContext &sig) {
271   ScopedInErrorReport in_report(/*fatal*/ true);
272   ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig, signo);
273   in_report.ReportError(error);
274 }
275
276 void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
277   ScopedInErrorReport in_report;
278   ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
279   in_report.ReportError(error);
280 }
281
282 void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
283                                  BufferedStackTrace *free_stack) {
284   ScopedInErrorReport in_report;
285   ErrorNewDeleteSizeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
286                                    delete_size);
287   in_report.ReportError(error);
288 }
289
290 void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
291   ScopedInErrorReport in_report;
292   ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
293   in_report.ReportError(error);
294 }
295
296 void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
297                              AllocType alloc_type,
298                              AllocType dealloc_type) {
299   ScopedInErrorReport in_report;
300   ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
301                                alloc_type, dealloc_type);
302   in_report.ReportError(error);
303 }
304
305 void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
306   ScopedInErrorReport in_report;
307   ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
308   in_report.ReportError(error);
309 }
310
311 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
312                                              BufferedStackTrace *stack) {
313   ScopedInErrorReport in_report;
314   ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
315                                                addr);
316   in_report.ReportError(error);
317 }
318
319 void ReportStringFunctionMemoryRangesOverlap(const char *function,
320                                              const char *offset1, uptr length1,
321                                              const char *offset2, uptr length2,
322                                              BufferedStackTrace *stack) {
323   ScopedInErrorReport in_report;
324   ErrorStringFunctionMemoryRangesOverlap error(
325       GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
326       length2, function);
327   in_report.ReportError(error);
328 }
329
330 void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
331                                       BufferedStackTrace *stack) {
332   ScopedInErrorReport in_report;
333   ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
334                                         size);
335   in_report.ReportError(error);
336 }
337
338 void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
339                                                   uptr old_mid, uptr new_mid,
340                                                   BufferedStackTrace *stack) {
341   ScopedInErrorReport in_report;
342   ErrorBadParamsToAnnotateContiguousContainer error(
343       GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
344   in_report.ReportError(error);
345 }
346
347 void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
348                         const __asan_global *g2, u32 stack_id2) {
349   ScopedInErrorReport in_report;
350   ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
351                           stack_id2);
352   in_report.ReportError(error);
353 }
354
355 // ----------------------- CheckForInvalidPointerPair ----------- {{{1
356 static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
357                                               uptr a1, uptr a2) {
358   ScopedInErrorReport in_report;
359   ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
360   in_report.ReportError(error);
361 }
362
363 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
364   if (!flags()->detect_invalid_pointer_pairs) return;
365   uptr a1 = reinterpret_cast<uptr>(p1);
366   uptr a2 = reinterpret_cast<uptr>(p2);
367   AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
368   AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
369   bool valid1 = chunk1.IsAllocated();
370   bool valid2 = chunk2.IsAllocated();
371   if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) {
372     GET_CALLER_PC_BP_SP;
373     return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
374   }
375 }
376 // ----------------------- Mac-specific reports ----------------- {{{1
377
378 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
379                                BufferedStackTrace *stack) {
380   ScopedInErrorReport in_report;
381   Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
382              "This is an unrecoverable problem, exiting now.\n",
383              addr);
384   PrintZoneForPointer(addr, zone_ptr, zone_name);
385   stack->Print();
386   DescribeAddressIfHeap(addr);
387 }
388
389 // -------------- SuppressErrorReport -------------- {{{1
390 // Avoid error reports duplicating for ASan recover mode.
391 static bool SuppressErrorReport(uptr pc) {
392   if (!common_flags()->suppress_equal_pcs) return false;
393   for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
394     uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
395     if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
396                                                    pc, memory_order_relaxed))
397       return false;
398     if (cmp == pc) return true;
399   }
400   Die();
401 }
402
403 void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
404                         uptr access_size, u32 exp, bool fatal) {
405   if (!fatal && SuppressErrorReport(pc)) return;
406   ENABLE_FRAME_POINTER;
407
408   // Optimization experiments.
409   // The experiments can be used to evaluate potential optimizations that remove
410   // instrumentation (assess false negatives). Instead of completely removing
411   // some instrumentation, compiler can emit special calls into runtime
412   // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
413   // mask of experiments (exp).
414   // The reaction to a non-zero value of exp is to be defined.
415   (void)exp;
416
417   ScopedInErrorReport in_report(fatal);
418   ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
419                      access_size);
420   in_report.ReportError(error);
421 }
422
423 }  // namespace __asan
424
425 // --------------------------- Interface --------------------- {{{1
426 using namespace __asan;  // NOLINT
427
428 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
429                          uptr access_size, u32 exp) {
430   ENABLE_FRAME_POINTER;
431   bool fatal = flags()->halt_on_error;
432   ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
433 }
434
435 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
436   BlockingMutexLock l(&error_message_buf_mutex);
437   error_report_callback = callback;
438 }
439
440 void __asan_describe_address(uptr addr) {
441   // Thread registry must be locked while we're describing an address.
442   asanThreadRegistry().Lock();
443   PrintAddressDescription(addr, 1, "");
444   asanThreadRegistry().Unlock();
445 }
446
447 int __asan_report_present() {
448   return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
449 }
450
451 uptr __asan_get_report_pc() {
452   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
453     return ScopedInErrorReport::CurrentError().Generic.pc;
454   return 0;
455 }
456
457 uptr __asan_get_report_bp() {
458   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
459     return ScopedInErrorReport::CurrentError().Generic.bp;
460   return 0;
461 }
462
463 uptr __asan_get_report_sp() {
464   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
465     return ScopedInErrorReport::CurrentError().Generic.sp;
466   return 0;
467 }
468
469 uptr __asan_get_report_address() {
470   ErrorDescription &err = ScopedInErrorReport::CurrentError();
471   if (err.kind == kErrorKindGeneric)
472     return err.Generic.addr_description.Address();
473   else if (err.kind == kErrorKindDoubleFree)
474     return err.DoubleFree.addr_description.addr;
475   return 0;
476 }
477
478 int __asan_get_report_access_type() {
479   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
480     return ScopedInErrorReport::CurrentError().Generic.is_write;
481   return 0;
482 }
483
484 uptr __asan_get_report_access_size() {
485   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
486     return ScopedInErrorReport::CurrentError().Generic.access_size;
487   return 0;
488 }
489
490 const char *__asan_get_report_description() {
491   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
492     return ScopedInErrorReport::CurrentError().Generic.bug_descr;
493   return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
494 }
495
496 extern "C" {
497 SANITIZER_INTERFACE_ATTRIBUTE
498 void __sanitizer_ptr_sub(void *a, void *b) {
499   CheckForInvalidPointerPair(a, b);
500 }
501 SANITIZER_INTERFACE_ATTRIBUTE
502 void __sanitizer_ptr_cmp(void *a, void *b) {
503   CheckForInvalidPointerPair(a, b);
504 }
505 } // extern "C"
506
507 // Provide default implementation of __asan_on_error that does nothing
508 // and may be overriden by user.
509 SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}