]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_report.cc
MFV r329799, r329800:
[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(), byte >> 4,
64               byte & 15, d.Default(), after);
65 }
66
67 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
68                                 const char *zone_name) {
69   if (zone_ptr) {
70     if (zone_name) {
71       Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
72                  ptr, zone_ptr, zone_name);
73     } else {
74       Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
75                  ptr, zone_ptr);
76     }
77   } else {
78     Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
79   }
80 }
81
82 // ---------------------- Address Descriptions ------------------- {{{1
83
84 bool ParseFrameDescription(const char *frame_descr,
85                            InternalMmapVector<StackVarDescr> *vars) {
86   CHECK(frame_descr);
87   char *p;
88   // This string is created by the compiler and has the following form:
89   // "n alloc_1 alloc_2 ... alloc_n"
90   // where alloc_i looks like "offset size len ObjectName"
91   // or                       "offset size len ObjectName:line".
92   uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
93   if (n_objects == 0)
94     return false;
95
96   for (uptr i = 0; i < n_objects; i++) {
97     uptr beg  = (uptr)internal_simple_strtoll(p, &p, 10);
98     uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
99     uptr len  = (uptr)internal_simple_strtoll(p, &p, 10);
100     if (beg == 0 || size == 0 || *p != ' ') {
101       return false;
102     }
103     p++;
104     char *colon_pos = internal_strchr(p, ':');
105     uptr line = 0;
106     uptr name_len = len;
107     if (colon_pos != nullptr && colon_pos < p + len) {
108       name_len = colon_pos - p;
109       line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
110     }
111     StackVarDescr var = {beg, size, p, name_len, line};
112     vars->push_back(var);
113     p += len;
114   }
115
116   return true;
117 }
118
119 // -------------------- Different kinds of reports ----------------- {{{1
120
121 // Use ScopedInErrorReport to run common actions just before and
122 // immediately after printing error report.
123 class ScopedInErrorReport {
124  public:
125   explicit ScopedInErrorReport(bool fatal = false)
126       : halt_on_error_(fatal || flags()->halt_on_error) {
127     // Make sure the registry and sanitizer report mutexes are locked while
128     // we're printing an error report.
129     // We can lock them only here to avoid self-deadlock in case of
130     // recursive reports.
131     asanThreadRegistry().Lock();
132     Printf(
133         "=================================================================\n");
134   }
135
136   ~ScopedInErrorReport() {
137     ASAN_ON_ERROR();
138     if (current_error_.IsValid()) current_error_.Print();
139
140     // Make sure the current thread is announced.
141     DescribeThread(GetCurrentThread());
142     // We may want to grab this lock again when printing stats.
143     asanThreadRegistry().Unlock();
144     // Print memory stats.
145     if (flags()->print_stats)
146       __asan_print_accumulated_stats();
147
148     if (common_flags()->print_cmdline)
149       PrintCmdline();
150
151     if (common_flags()->print_module_map == 2) PrintModuleMap();
152
153     // Copy the message buffer so that we could start logging without holding a
154     // lock that gets aquired during printing.
155     InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
156     {
157       BlockingMutexLock l(&error_message_buf_mutex);
158       internal_memcpy(buffer_copy.data(),
159                       error_message_buffer, kErrorMessageBufferSize);
160     }
161
162     LogFullErrorReport(buffer_copy.data());
163
164     if (error_report_callback) {
165       error_report_callback(buffer_copy.data());
166     }
167
168     if (halt_on_error_ && common_flags()->abort_on_error) {
169       // On Android the message is truncated to 512 characters.
170       // FIXME: implement "compact" error format, possibly without, or with
171       // highly compressed stack traces?
172       // FIXME: or just use the summary line as abort message?
173       SetAbortMessage(buffer_copy.data());
174     }
175
176     // In halt_on_error = false mode, reset the current error object (before
177     // unlocking).
178     if (!halt_on_error_)
179       internal_memset(&current_error_, 0, sizeof(current_error_));
180
181     if (halt_on_error_) {
182       Report("ABORTING\n");
183       Die();
184     }
185   }
186
187   void ReportError(const ErrorDescription &description) {
188     // Can only report one error per ScopedInErrorReport.
189     CHECK_EQ(current_error_.kind, kErrorKindInvalid);
190     current_error_ = description;
191   }
192
193   static ErrorDescription &CurrentError() {
194     return current_error_;
195   }
196
197  private:
198   ScopedErrorReportLock error_report_lock_;
199   // Error currently being reported. This enables the destructor to interact
200   // with the debugger and point it to an error description.
201   static ErrorDescription current_error_;
202   bool halt_on_error_;
203 };
204
205 ErrorDescription ScopedInErrorReport::current_error_;
206
207 void ReportDeadlySignal(const SignalContext &sig) {
208   ScopedInErrorReport in_report(/*fatal*/ true);
209   ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig);
210   in_report.ReportError(error);
211 }
212
213 void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
214   ScopedInErrorReport in_report;
215   ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
216   in_report.ReportError(error);
217 }
218
219 void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
220                                  uptr delete_alignment,
221                                  BufferedStackTrace *free_stack) {
222   ScopedInErrorReport in_report;
223   ErrorNewDeleteTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
224                                    delete_size, delete_alignment);
225   in_report.ReportError(error);
226 }
227
228 void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
229   ScopedInErrorReport in_report;
230   ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
231   in_report.ReportError(error);
232 }
233
234 void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
235                              AllocType alloc_type,
236                              AllocType dealloc_type) {
237   ScopedInErrorReport in_report;
238   ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
239                                alloc_type, dealloc_type);
240   in_report.ReportError(error);
241 }
242
243 void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
244   ScopedInErrorReport in_report;
245   ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
246   in_report.ReportError(error);
247 }
248
249 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
250                                              BufferedStackTrace *stack) {
251   ScopedInErrorReport in_report;
252   ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
253                                                addr);
254   in_report.ReportError(error);
255 }
256
257 void ReportStringFunctionMemoryRangesOverlap(const char *function,
258                                              const char *offset1, uptr length1,
259                                              const char *offset2, uptr length2,
260                                              BufferedStackTrace *stack) {
261   ScopedInErrorReport in_report;
262   ErrorStringFunctionMemoryRangesOverlap error(
263       GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
264       length2, function);
265   in_report.ReportError(error);
266 }
267
268 void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
269                                       BufferedStackTrace *stack) {
270   ScopedInErrorReport in_report;
271   ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
272                                         size);
273   in_report.ReportError(error);
274 }
275
276 void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
277                                                   uptr old_mid, uptr new_mid,
278                                                   BufferedStackTrace *stack) {
279   ScopedInErrorReport in_report;
280   ErrorBadParamsToAnnotateContiguousContainer error(
281       GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
282   in_report.ReportError(error);
283 }
284
285 void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
286                         const __asan_global *g2, u32 stack_id2) {
287   ScopedInErrorReport in_report;
288   ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
289                           stack_id2);
290   in_report.ReportError(error);
291 }
292
293 // ----------------------- CheckForInvalidPointerPair ----------- {{{1
294 static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
295                                               uptr a1, uptr a2) {
296   ScopedInErrorReport in_report;
297   ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
298   in_report.ReportError(error);
299 }
300
301 static bool IsInvalidPointerPair(uptr a1, uptr a2) {
302   if (a1 == a2)
303     return false;
304
305   // 256B in shadow memory can be iterated quite fast
306   static const uptr kMaxOffset = 2048;
307
308   uptr left = a1 < a2 ? a1 : a2;
309   uptr right = a1 < a2 ? a2 : a1;
310   uptr offset = right - left;
311   if (offset <= kMaxOffset)
312     return __asan_region_is_poisoned(left, offset);
313
314   AsanThread *t = GetCurrentThread();
315
316   // check whether left is a stack memory pointer
317   if (uptr shadow_offset1 = t->GetStackVariableShadowStart(left)) {
318     uptr shadow_offset2 = t->GetStackVariableShadowStart(right);
319     return shadow_offset2 == 0 || shadow_offset1 != shadow_offset2;
320   }
321
322   // check whether left is a heap memory address
323   HeapAddressDescription hdesc1, hdesc2;
324   if (GetHeapAddressInformation(left, 0, &hdesc1) &&
325       hdesc1.chunk_access.access_type == kAccessTypeInside)
326     return !GetHeapAddressInformation(right, 0, &hdesc2) ||
327         hdesc2.chunk_access.access_type != kAccessTypeInside ||
328         hdesc1.chunk_access.chunk_begin != hdesc2.chunk_access.chunk_begin;
329
330   // check whether left is an address of a global variable
331   GlobalAddressDescription gdesc1, gdesc2;
332   if (GetGlobalAddressInformation(left, 0, &gdesc1))
333     return !GetGlobalAddressInformation(right - 1, 0, &gdesc2) ||
334         !gdesc1.PointsInsideTheSameVariable(gdesc2);
335
336   if (t->GetStackVariableShadowStart(right) ||
337       GetHeapAddressInformation(right, 0, &hdesc2) ||
338       GetGlobalAddressInformation(right - 1, 0, &gdesc2))
339     return true;
340
341   // At this point we know nothing about both a1 and a2 addresses.
342   return false;
343 }
344
345 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
346   if (!flags()->detect_invalid_pointer_pairs) return;
347   uptr a1 = reinterpret_cast<uptr>(p1);
348   uptr a2 = reinterpret_cast<uptr>(p2);
349
350   if (IsInvalidPointerPair(a1, a2)) {
351     GET_CALLER_PC_BP_SP;
352     ReportInvalidPointerPair(pc, bp, sp, a1, a2);
353   }
354 }
355 // ----------------------- Mac-specific reports ----------------- {{{1
356
357 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
358                                BufferedStackTrace *stack) {
359   ScopedInErrorReport in_report;
360   Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
361              "This is an unrecoverable problem, exiting now.\n",
362              addr);
363   PrintZoneForPointer(addr, zone_ptr, zone_name);
364   stack->Print();
365   DescribeAddressIfHeap(addr);
366 }
367
368 // -------------- SuppressErrorReport -------------- {{{1
369 // Avoid error reports duplicating for ASan recover mode.
370 static bool SuppressErrorReport(uptr pc) {
371   if (!common_flags()->suppress_equal_pcs) return false;
372   for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
373     uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
374     if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
375                                                    pc, memory_order_relaxed))
376       return false;
377     if (cmp == pc) return true;
378   }
379   Die();
380 }
381
382 void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
383                         uptr access_size, u32 exp, bool fatal) {
384   if (!fatal && SuppressErrorReport(pc)) return;
385   ENABLE_FRAME_POINTER;
386
387   // Optimization experiments.
388   // The experiments can be used to evaluate potential optimizations that remove
389   // instrumentation (assess false negatives). Instead of completely removing
390   // some instrumentation, compiler can emit special calls into runtime
391   // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
392   // mask of experiments (exp).
393   // The reaction to a non-zero value of exp is to be defined.
394   (void)exp;
395
396   ScopedInErrorReport in_report(fatal);
397   ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
398                      access_size);
399   in_report.ReportError(error);
400 }
401
402 }  // namespace __asan
403
404 // --------------------------- Interface --------------------- {{{1
405 using namespace __asan;  // NOLINT
406
407 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
408                          uptr access_size, u32 exp) {
409   ENABLE_FRAME_POINTER;
410   bool fatal = flags()->halt_on_error;
411   ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
412 }
413
414 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
415   BlockingMutexLock l(&error_message_buf_mutex);
416   error_report_callback = callback;
417 }
418
419 void __asan_describe_address(uptr addr) {
420   // Thread registry must be locked while we're describing an address.
421   asanThreadRegistry().Lock();
422   PrintAddressDescription(addr, 1, "");
423   asanThreadRegistry().Unlock();
424 }
425
426 int __asan_report_present() {
427   return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
428 }
429
430 uptr __asan_get_report_pc() {
431   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
432     return ScopedInErrorReport::CurrentError().Generic.pc;
433   return 0;
434 }
435
436 uptr __asan_get_report_bp() {
437   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
438     return ScopedInErrorReport::CurrentError().Generic.bp;
439   return 0;
440 }
441
442 uptr __asan_get_report_sp() {
443   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
444     return ScopedInErrorReport::CurrentError().Generic.sp;
445   return 0;
446 }
447
448 uptr __asan_get_report_address() {
449   ErrorDescription &err = ScopedInErrorReport::CurrentError();
450   if (err.kind == kErrorKindGeneric)
451     return err.Generic.addr_description.Address();
452   else if (err.kind == kErrorKindDoubleFree)
453     return err.DoubleFree.addr_description.addr;
454   return 0;
455 }
456
457 int __asan_get_report_access_type() {
458   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
459     return ScopedInErrorReport::CurrentError().Generic.is_write;
460   return 0;
461 }
462
463 uptr __asan_get_report_access_size() {
464   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
465     return ScopedInErrorReport::CurrentError().Generic.access_size;
466   return 0;
467 }
468
469 const char *__asan_get_report_description() {
470   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
471     return ScopedInErrorReport::CurrentError().Generic.bug_descr;
472   return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
473 }
474
475 extern "C" {
476 SANITIZER_INTERFACE_ATTRIBUTE
477 void __sanitizer_ptr_sub(void *a, void *b) {
478   CheckForInvalidPointerPair(a, b);
479 }
480 SANITIZER_INTERFACE_ATTRIBUTE
481 void __sanitizer_ptr_cmp(void *a, void *b) {
482   CheckForInvalidPointerPair(a, b);
483 }
484 } // extern "C"
485
486 // Provide default implementation of __asan_on_error that does nothing
487 // and may be overriden by user.
488 SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}