1 //=-- lsan_common.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of LeakSanitizer.
10 // Implementation of common leak checking functionality.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "lsan_common.h"
15 
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_flag_parser.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_placement_new.h"
20 #include "sanitizer_common/sanitizer_procmaps.h"
21 #include "sanitizer_common/sanitizer_report_decorator.h"
22 #include "sanitizer_common/sanitizer_stackdepot.h"
23 #include "sanitizer_common/sanitizer_stacktrace.h"
24 #include "sanitizer_common/sanitizer_suppressions.h"
25 #include "sanitizer_common/sanitizer_thread_registry.h"
26 #include "sanitizer_common/sanitizer_tls_get_addr.h"
27 
28 #if CAN_SANITIZE_LEAKS
29 namespace __lsan {
30 
31 // This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
32 // also to protect the global list of root regions.
33 Mutex global_mutex;
34 
35 Flags lsan_flags;
36 
37 
38 void DisableCounterUnderflow() {
39   if (common_flags()->detect_leaks) {
40     Report("Unmatched call to __lsan_enable().\n");
41     Die();
42   }
43 }
44 
45 void Flags::SetDefaults() {
46 #define LSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
47 #include "lsan_flags.inc"
48 #undef LSAN_FLAG
49 }
50 
51 void RegisterLsanFlags(FlagParser *parser, Flags *f) {
52 #define LSAN_FLAG(Type, Name, DefaultValue, Description) \
53   RegisterFlag(parser, #Name, Description, &f->Name);
54 #include "lsan_flags.inc"
55 #undef LSAN_FLAG
56 }
57 
58 #define LOG_POINTERS(...)                           \
59   do {                                              \
60     if (flags()->log_pointers) Report(__VA_ARGS__); \
61   } while (0)
62 
63 #define LOG_THREADS(...)                           \
64   do {                                             \
65     if (flags()->log_threads) Report(__VA_ARGS__); \
66   } while (0)
67 
68 class LeakSuppressionContext {
69   bool parsed = false;
70   SuppressionContext context;
71   bool suppressed_stacks_sorted = true;
72   InternalMmapVector<u32> suppressed_stacks;
73 
74   Suppression *GetSuppressionForAddr(uptr addr);
75   void LazyInit();
76 
77  public:
78   LeakSuppressionContext(const char *supprression_types[],
79                          int suppression_types_num)
80       : context(supprression_types, suppression_types_num) {}
81 
82   Suppression *GetSuppressionForStack(u32 stack_trace_id,
83                                       const StackTrace &stack);
84 
85   const InternalMmapVector<u32> &GetSortedSuppressedStacks() {
86     if (!suppressed_stacks_sorted) {
87       suppressed_stacks_sorted = true;
88       SortAndDedup(suppressed_stacks);
89     }
90     return suppressed_stacks;
91   }
92   void PrintMatchedSuppressions();
93 };
94 
95 ALIGNED(64) static char suppression_placeholder[sizeof(LeakSuppressionContext)];
96 static LeakSuppressionContext *suppression_ctx = nullptr;
97 static const char kSuppressionLeak[] = "leak";
98 static const char *kSuppressionTypes[] = { kSuppressionLeak };
99 static const char kStdSuppressions[] =
100 #if SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
101     // For more details refer to the SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
102     // definition.
103     "leak:*pthread_exit*\n"
104 #endif  // SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
105 #if SANITIZER_MAC
106     // For Darwin and os_log/os_trace: https://reviews.llvm.org/D35173
107     "leak:*_os_trace*\n"
108 #endif
109     // TLS leak in some glibc versions, described in
110     // https://sourceware.org/bugzilla/show_bug.cgi?id=12650.
111     "leak:*tls_get_addr*\n";
112 
113 void InitializeSuppressions() {
114   CHECK_EQ(nullptr, suppression_ctx);
115   suppression_ctx = new (suppression_placeholder)
116       LeakSuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
117 }
118 
119 void LeakSuppressionContext::LazyInit() {
120   if (!parsed) {
121     parsed = true;
122     context.ParseFromFile(flags()->suppressions);
123     if (&__lsan_default_suppressions)
124       context.Parse(__lsan_default_suppressions());
125     context.Parse(kStdSuppressions);
126   }
127 }
128 
129 static LeakSuppressionContext *GetSuppressionContext() {
130   CHECK(suppression_ctx);
131   return suppression_ctx;
132 }
133 
134 static InternalMmapVector<RootRegion> *root_regions;
135 
136 InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
137 
138 void InitializeRootRegions() {
139   CHECK(!root_regions);
140   ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
141   root_regions = new (placeholder) InternalMmapVector<RootRegion>();
142 }
143 
144 void InitCommonLsan() {
145   InitializeRootRegions();
146   if (common_flags()->detect_leaks) {
147     // Initialization which can fail or print warnings should only be done if
148     // LSan is actually enabled.
149     InitializeSuppressions();
150     InitializePlatformSpecificModules();
151   }
152 }
153 
154 class Decorator: public __sanitizer::SanitizerCommonDecorator {
155  public:
156   Decorator() : SanitizerCommonDecorator() { }
157   const char *Error() { return Red(); }
158   const char *Leak() { return Blue(); }
159 };
160 
161 static inline bool CanBeAHeapPointer(uptr p) {
162   // Since our heap is located in mmap-ed memory, we can assume a sensible lower
163   // bound on heap addresses.
164   const uptr kMinAddress = 4 * 4096;
165   if (p < kMinAddress) return false;
166 #if defined(__x86_64__)
167   // Accept only canonical form user-space addresses.
168   return ((p >> 47) == 0);
169 #elif defined(__mips64)
170   return ((p >> 40) == 0);
171 #elif defined(__aarch64__)
172   unsigned runtimeVMA =
173     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
174   return ((p >> runtimeVMA) == 0);
175 #else
176   return true;
177 #endif
178 }
179 
180 // Scans the memory range, looking for byte patterns that point into allocator
181 // chunks. Marks those chunks with |tag| and adds them to |frontier|.
182 // There are two usage modes for this function: finding reachable chunks
183 // (|tag| = kReachable) and finding indirectly leaked chunks
184 // (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
185 // so |frontier| = 0.
186 void ScanRangeForPointers(uptr begin, uptr end,
187                           Frontier *frontier,
188                           const char *region_type, ChunkTag tag) {
189   CHECK(tag == kReachable || tag == kIndirectlyLeaked);
190   const uptr alignment = flags()->pointer_alignment();
191   LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, begin, end);
192   uptr pp = begin;
193   if (pp % alignment)
194     pp = pp + alignment - pp % alignment;
195   for (; pp + sizeof(void *) <= end; pp += alignment) {
196     void *p = *reinterpret_cast<void **>(pp);
197     if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
198     uptr chunk = PointsIntoChunk(p);
199     if (!chunk) continue;
200     // Pointers to self don't count. This matters when tag == kIndirectlyLeaked.
201     if (chunk == begin) continue;
202     LsanMetadata m(chunk);
203     if (m.tag() == kReachable || m.tag() == kIgnored) continue;
204 
205     // Do this check relatively late so we can log only the interesting cases.
206     if (!flags()->use_poisoned && WordIsPoisoned(pp)) {
207       LOG_POINTERS(
208           "%p is poisoned: ignoring %p pointing into chunk %p-%p of size "
209           "%zu.\n",
210           pp, p, chunk, chunk + m.requested_size(), m.requested_size());
211       continue;
212     }
213 
214     m.set_tag(tag);
215     LOG_POINTERS("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
216                  chunk, chunk + m.requested_size(), m.requested_size());
217     if (frontier)
218       frontier->push_back(chunk);
219   }
220 }
221 
222 // Scans a global range for pointers
223 void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
224   uptr allocator_begin = 0, allocator_end = 0;
225   GetAllocatorGlobalRange(&allocator_begin, &allocator_end);
226   if (begin <= allocator_begin && allocator_begin < end) {
227     CHECK_LE(allocator_begin, allocator_end);
228     CHECK_LE(allocator_end, end);
229     if (begin < allocator_begin)
230       ScanRangeForPointers(begin, allocator_begin, frontier, "GLOBAL",
231                            kReachable);
232     if (allocator_end < end)
233       ScanRangeForPointers(allocator_end, end, frontier, "GLOBAL", kReachable);
234   } else {
235     ScanRangeForPointers(begin, end, frontier, "GLOBAL", kReachable);
236   }
237 }
238 
239 void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg) {
240   Frontier *frontier = reinterpret_cast<Frontier *>(arg);
241   ScanRangeForPointers(begin, end, frontier, "FAKE STACK", kReachable);
242 }
243 
244 #if SANITIZER_FUCHSIA
245 
246 // Fuchsia handles all threads together with its own callback.
247 static void ProcessThreads(SuspendedThreadsList const &, Frontier *) {}
248 
249 #else
250 
251 #if SANITIZER_ANDROID
252 // FIXME: Move this out into *libcdep.cpp
253 extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_iterate_dynamic_tls(
254     pid_t, void (*cb)(void *, void *, uptr, void *), void *);
255 #endif
256 
257 static void ProcessThreadRegistry(Frontier *frontier) {
258   InternalMmapVector<uptr> ptrs;
259   GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
260       GetAdditionalThreadContextPtrs, &ptrs);
261 
262   for (uptr i = 0; i < ptrs.size(); ++i) {
263     void *ptr = reinterpret_cast<void *>(ptrs[i]);
264     uptr chunk = PointsIntoChunk(ptr);
265     if (!chunk)
266       continue;
267     LsanMetadata m(chunk);
268     if (!m.allocated())
269       continue;
270 
271     // Mark as reachable and add to frontier.
272     LOG_POINTERS("Treating pointer %p from ThreadContext as reachable\n", ptr);
273     m.set_tag(kReachable);
274     frontier->push_back(chunk);
275   }
276 }
277 
278 // Scans thread data (stacks and TLS) for heap pointers.
279 static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
280                            Frontier *frontier) {
281   InternalMmapVector<uptr> registers;
282   for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) {
283     tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i));
284     LOG_THREADS("Processing thread %d.\n", os_id);
285     uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
286     DTLS *dtls;
287     bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
288                                               &tls_begin, &tls_end,
289                                               &cache_begin, &cache_end, &dtls);
290     if (!thread_found) {
291       // If a thread can't be found in the thread registry, it's probably in the
292       // process of destruction. Log this event and move on.
293       LOG_THREADS("Thread %d not found in registry.\n", os_id);
294       continue;
295     }
296     uptr sp;
297     PtraceRegistersStatus have_registers =
298         suspended_threads.GetRegistersAndSP(i, &registers, &sp);
299     if (have_registers != REGISTERS_AVAILABLE) {
300       Report("Unable to get registers from thread %d.\n", os_id);
301       // If unable to get SP, consider the entire stack to be reachable unless
302       // GetRegistersAndSP failed with ESRCH.
303       if (have_registers == REGISTERS_UNAVAILABLE_FATAL) continue;
304       sp = stack_begin;
305     }
306 
307     if (flags()->use_registers && have_registers) {
308       uptr registers_begin = reinterpret_cast<uptr>(registers.data());
309       uptr registers_end =
310           reinterpret_cast<uptr>(registers.data() + registers.size());
311       ScanRangeForPointers(registers_begin, registers_end, frontier,
312                            "REGISTERS", kReachable);
313     }
314 
315     if (flags()->use_stacks) {
316       LOG_THREADS("Stack at %p-%p (SP = %p).\n", stack_begin, stack_end, sp);
317       if (sp < stack_begin || sp >= stack_end) {
318         // SP is outside the recorded stack range (e.g. the thread is running a
319         // signal handler on alternate stack, or swapcontext was used).
320         // Again, consider the entire stack range to be reachable.
321         LOG_THREADS("WARNING: stack pointer not in stack range.\n");
322         uptr page_size = GetPageSizeCached();
323         int skipped = 0;
324         while (stack_begin < stack_end &&
325                !IsAccessibleMemoryRange(stack_begin, 1)) {
326           skipped++;
327           stack_begin += page_size;
328         }
329         LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n",
330                     skipped, stack_begin, stack_end);
331       } else {
332         // Shrink the stack range to ignore out-of-scope values.
333         stack_begin = sp;
334       }
335       ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
336                            kReachable);
337       ForEachExtraStackRange(os_id, ForEachExtraStackRangeCb, frontier);
338     }
339 
340     if (flags()->use_tls) {
341       if (tls_begin) {
342         LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end);
343         // If the tls and cache ranges don't overlap, scan full tls range,
344         // otherwise, only scan the non-overlapping portions
345         if (cache_begin == cache_end || tls_end < cache_begin ||
346             tls_begin > cache_end) {
347           ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
348         } else {
349           if (tls_begin < cache_begin)
350             ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
351                                  kReachable);
352           if (tls_end > cache_end)
353             ScanRangeForPointers(cache_end, tls_end, frontier, "TLS",
354                                  kReachable);
355         }
356       }
357 #if SANITIZER_ANDROID
358       auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/,
359                      void *arg) -> void {
360         ScanRangeForPointers(reinterpret_cast<uptr>(dtls_begin),
361                              reinterpret_cast<uptr>(dtls_end),
362                              reinterpret_cast<Frontier *>(arg), "DTLS",
363                              kReachable);
364       };
365 
366       // FIXME: There might be a race-condition here (and in Bionic) if the
367       // thread is suspended in the middle of updating its DTLS. IOWs, we
368       // could scan already freed memory. (probably fine for now)
369       __libc_iterate_dynamic_tls(os_id, cb, frontier);
370 #else
371       if (dtls && !DTLSInDestruction(dtls)) {
372         ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) {
373           uptr dtls_beg = dtv.beg;
374           uptr dtls_end = dtls_beg + dtv.size;
375           if (dtls_beg < dtls_end) {
376             LOG_THREADS("DTLS %zu at %p-%p.\n", id, dtls_beg, dtls_end);
377             ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
378                                  kReachable);
379           }
380         });
381       } else {
382         // We are handling a thread with DTLS under destruction. Log about
383         // this and continue.
384         LOG_THREADS("Thread %d has DTLS under destruction.\n", os_id);
385       }
386 #endif
387     }
388   }
389 
390   // Add pointers reachable from ThreadContexts
391   ProcessThreadRegistry(frontier);
392 }
393 
394 #endif  // SANITIZER_FUCHSIA
395 
396 void ScanRootRegion(Frontier *frontier, const RootRegion &root_region,
397                     uptr region_begin, uptr region_end, bool is_readable) {
398   uptr intersection_begin = Max(root_region.begin, region_begin);
399   uptr intersection_end = Min(region_end, root_region.begin + root_region.size);
400   if (intersection_begin >= intersection_end) return;
401   LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
402                root_region.begin, root_region.begin + root_region.size,
403                region_begin, region_end,
404                is_readable ? "readable" : "unreadable");
405   if (is_readable)
406     ScanRangeForPointers(intersection_begin, intersection_end, frontier, "ROOT",
407                          kReachable);
408 }
409 
410 static void ProcessRootRegion(Frontier *frontier,
411                               const RootRegion &root_region) {
412   MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
413   MemoryMappedSegment segment;
414   while (proc_maps.Next(&segment)) {
415     ScanRootRegion(frontier, root_region, segment.start, segment.end,
416                    segment.IsReadable());
417   }
418 }
419 
420 // Scans root regions for heap pointers.
421 static void ProcessRootRegions(Frontier *frontier) {
422   if (!flags()->use_root_regions) return;
423   CHECK(root_regions);
424   for (uptr i = 0; i < root_regions->size(); i++) {
425     ProcessRootRegion(frontier, (*root_regions)[i]);
426   }
427 }
428 
429 static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
430   while (frontier->size()) {
431     uptr next_chunk = frontier->back();
432     frontier->pop_back();
433     LsanMetadata m(next_chunk);
434     ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
435                          "HEAP", tag);
436   }
437 }
438 
439 // ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
440 // which are reachable from it as indirectly leaked.
441 static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
442   chunk = GetUserBegin(chunk);
443   LsanMetadata m(chunk);
444   if (m.allocated() && m.tag() != kReachable) {
445     ScanRangeForPointers(chunk, chunk + m.requested_size(),
446                          /* frontier */ nullptr, "HEAP", kIndirectlyLeaked);
447   }
448 }
449 
450 static void IgnoredSuppressedCb(uptr chunk, void *arg) {
451   CHECK(arg);
452   chunk = GetUserBegin(chunk);
453   LsanMetadata m(chunk);
454   if (!m.allocated() || m.tag() == kIgnored)
455     return;
456 
457   const InternalMmapVector<u32> &suppressed =
458       *static_cast<const InternalMmapVector<u32> *>(arg);
459   uptr idx = InternalLowerBound(suppressed, m.stack_trace_id());
460   if (idx >= suppressed.size() || m.stack_trace_id() != suppressed[idx])
461     return;
462 
463   LOG_POINTERS("Suppressed: chunk %p-%p of size %zu.\n", chunk,
464                chunk + m.requested_size(), m.requested_size());
465   m.set_tag(kIgnored);
466 }
467 
468 // ForEachChunk callback. If chunk is marked as ignored, adds its address to
469 // frontier.
470 static void CollectIgnoredCb(uptr chunk, void *arg) {
471   CHECK(arg);
472   chunk = GetUserBegin(chunk);
473   LsanMetadata m(chunk);
474   if (m.allocated() && m.tag() == kIgnored) {
475     LOG_POINTERS("Ignored: chunk %p-%p of size %zu.\n",
476                  chunk, chunk + m.requested_size(), m.requested_size());
477     reinterpret_cast<Frontier *>(arg)->push_back(chunk);
478   }
479 }
480 
481 static uptr GetCallerPC(const StackTrace &stack) {
482   // The top frame is our malloc/calloc/etc. The next frame is the caller.
483   if (stack.size >= 2)
484     return stack.trace[1];
485   return 0;
486 }
487 
488 struct InvalidPCParam {
489   Frontier *frontier;
490   const StackDepotReverseMap *stack_depot;
491   bool skip_linker_allocations;
492 };
493 
494 // ForEachChunk callback. If the caller pc is invalid or is within the linker,
495 // mark as reachable. Called by ProcessPlatformSpecificAllocations.
496 static void MarkInvalidPCCb(uptr chunk, void *arg) {
497   CHECK(arg);
498   InvalidPCParam *param = reinterpret_cast<InvalidPCParam *>(arg);
499   chunk = GetUserBegin(chunk);
500   LsanMetadata m(chunk);
501   if (m.allocated() && m.tag() != kReachable && m.tag() != kIgnored) {
502     u32 stack_id = m.stack_trace_id();
503     uptr caller_pc = 0;
504     if (stack_id > 0)
505       caller_pc = GetCallerPC(param->stack_depot->Get(stack_id));
506     // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
507     // it as reachable, as we can't properly report its allocation stack anyway.
508     if (caller_pc == 0 || (param->skip_linker_allocations &&
509                            GetLinker()->containsAddress(caller_pc))) {
510       m.set_tag(kReachable);
511       param->frontier->push_back(chunk);
512     }
513   }
514 }
515 
516 // On Linux, treats all chunks allocated from ld-linux.so as reachable, which
517 // covers dynamically allocated TLS blocks, internal dynamic loader's loaded
518 // modules accounting etc.
519 // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
520 // They are allocated with a __libc_memalign() call in allocate_and_init()
521 // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
522 // blocks, but we can make sure they come from our own allocator by intercepting
523 // __libc_memalign(). On top of that, there is no easy way to reach them. Their
524 // addresses are stored in a dynamically allocated array (the DTV) which is
525 // referenced from the static TLS. Unfortunately, we can't just rely on the DTV
526 // being reachable from the static TLS, and the dynamic TLS being reachable from
527 // the DTV. This is because the initial DTV is allocated before our interception
528 // mechanism kicks in, and thus we don't recognize it as allocated memory. We
529 // can't special-case it either, since we don't know its size.
530 // Our solution is to include in the root set all allocations made from
531 // ld-linux.so (which is where allocate_and_init() is implemented). This is
532 // guaranteed to include all dynamic TLS blocks (and possibly other allocations
533 // which we don't care about).
534 // On all other platforms, this simply checks to ensure that the caller pc is
535 // valid before reporting chunks as leaked.
536 static void ProcessPC(Frontier *frontier,
537                       const StackDepotReverseMap &stack_depot) {
538   InvalidPCParam arg;
539   arg.frontier = frontier;
540   arg.stack_depot = &stack_depot;
541   arg.skip_linker_allocations =
542       flags()->use_tls && flags()->use_ld_allocations && GetLinker() != nullptr;
543   ForEachChunk(MarkInvalidPCCb, &arg);
544 }
545 
546 // Sets the appropriate tag on each chunk.
547 static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
548                               const StackDepotReverseMap &stack_depot,
549                               Frontier *frontier) {
550   const InternalMmapVector<u32> &suppressed_stacks =
551       GetSuppressionContext()->GetSortedSuppressedStacks();
552   if (!suppressed_stacks.empty()) {
553     ForEachChunk(IgnoredSuppressedCb,
554                  const_cast<InternalMmapVector<u32> *>(&suppressed_stacks));
555   }
556   ForEachChunk(CollectIgnoredCb, frontier);
557   ProcessGlobalRegions(frontier);
558   ProcessThreads(suspended_threads, frontier);
559   ProcessRootRegions(frontier);
560   FloodFillTag(frontier, kReachable);
561 
562   CHECK_EQ(0, frontier->size());
563   ProcessPC(frontier, stack_depot);
564 
565   // The check here is relatively expensive, so we do this in a separate flood
566   // fill. That way we can skip the check for chunks that are reachable
567   // otherwise.
568   LOG_POINTERS("Processing platform-specific allocations.\n");
569   ProcessPlatformSpecificAllocations(frontier);
570   FloodFillTag(frontier, kReachable);
571 
572   // Iterate over leaked chunks and mark those that are reachable from other
573   // leaked chunks.
574   LOG_POINTERS("Scanning leaked chunks.\n");
575   ForEachChunk(MarkIndirectlyLeakedCb, nullptr);
576 }
577 
578 // ForEachChunk callback. Resets the tags to pre-leak-check state.
579 static void ResetTagsCb(uptr chunk, void *arg) {
580   (void)arg;
581   chunk = GetUserBegin(chunk);
582   LsanMetadata m(chunk);
583   if (m.allocated() && m.tag() != kIgnored)
584     m.set_tag(kDirectlyLeaked);
585 }
586 
587 // ForEachChunk callback. Aggregates information about unreachable chunks into
588 // a LeakReport.
589 static void CollectLeaksCb(uptr chunk, void *arg) {
590   CHECK(arg);
591   LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
592   chunk = GetUserBegin(chunk);
593   LsanMetadata m(chunk);
594   if (!m.allocated()) return;
595   if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
596     leak_report->AddLeakedChunk(chunk, m.stack_trace_id(), m.requested_size(),
597                                 m.tag());
598   }
599 }
600 
601 void LeakSuppressionContext::PrintMatchedSuppressions() {
602   InternalMmapVector<Suppression *> matched;
603   context.GetMatched(&matched);
604   if (!matched.size())
605     return;
606   const char *line = "-----------------------------------------------------";
607   Printf("%s\n", line);
608   Printf("Suppressions used:\n");
609   Printf("  count      bytes template\n");
610   for (uptr i = 0; i < matched.size(); i++) {
611     Printf("%7zu %10zu %s\n",
612            static_cast<uptr>(atomic_load_relaxed(&matched[i]->hit_count)),
613            matched[i]->weight, matched[i]->templ);
614   }
615   Printf("%s\n\n", line);
616 }
617 
618 static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
619   const InternalMmapVector<tid_t> &suspended_threads =
620       *(const InternalMmapVector<tid_t> *)arg;
621   if (tctx->status == ThreadStatusRunning) {
622     uptr i = InternalLowerBound(suspended_threads, tctx->os_id);
623     if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
624       Report("Running thread %d was not suspended. False leaks are possible.\n",
625              tctx->os_id);
626   }
627 }
628 
629 #if SANITIZER_FUCHSIA
630 
631 // Fuchsia provides a libc interface that guarantees all threads are
632 // covered, and SuspendedThreadList is never really used.
633 static void ReportUnsuspendedThreads(const SuspendedThreadsList &) {}
634 
635 #else  // !SANITIZER_FUCHSIA
636 
637 static void ReportUnsuspendedThreads(
638     const SuspendedThreadsList &suspended_threads) {
639   InternalMmapVector<tid_t> threads(suspended_threads.ThreadCount());
640   for (uptr i = 0; i < suspended_threads.ThreadCount(); ++i)
641     threads[i] = suspended_threads.GetThreadID(i);
642 
643   Sort(threads.data(), threads.size());
644 
645   GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
646       &ReportIfNotSuspended, &threads);
647 }
648 
649 #endif  // !SANITIZER_FUCHSIA
650 
651 static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
652                                   void *arg) {
653   CheckForLeaksParam *param = reinterpret_cast<CheckForLeaksParam *>(arg);
654   CHECK(param);
655   CHECK(!param->success);
656   ReportUnsuspendedThreads(suspended_threads);
657   ClassifyAllChunks(suspended_threads, param->leak_report.stack_depot(),
658                     &param->frontier);
659   ForEachChunk(CollectLeaksCb, &param->leak_report);
660   // Clean up for subsequent leak checks. This assumes we did not overwrite any
661   // kIgnored tags.
662   ForEachChunk(ResetTagsCb, nullptr);
663   param->success = true;
664 }
665 
666 static bool PrintResults(LeakReport &report) {
667   uptr unsuppressed_count = report.UnsuppressedLeakCount();
668   if (unsuppressed_count) {
669     Decorator d;
670     Printf(
671         "\n"
672         "================================================================="
673         "\n");
674     Printf("%s", d.Error());
675     Report("ERROR: LeakSanitizer: detected memory leaks\n");
676     Printf("%s", d.Default());
677     report.ReportTopLeaks(flags()->max_leaks);
678   }
679   if (common_flags()->print_suppressions)
680     GetSuppressionContext()->PrintMatchedSuppressions();
681   if (unsuppressed_count > 0) {
682     report.PrintSummary();
683     return true;
684   }
685   return false;
686 }
687 
688 static bool CheckForLeaks() {
689   if (&__lsan_is_turned_off && __lsan_is_turned_off())
690     return false;
691   // Inside LockStuffAndStopTheWorld we can't run symbolizer, so we can't match
692   // suppressions. However if a stack id was previously suppressed, it should be
693   // suppressed in future checks as well.
694   for (int i = 0;; ++i) {
695     EnsureMainThreadIDIsCorrect();
696     CheckForLeaksParam param;
697     LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
698     if (!param.success) {
699       Report("LeakSanitizer has encountered a fatal error.\n");
700       Report(
701           "HINT: For debugging, try setting environment variable "
702           "LSAN_OPTIONS=verbosity=1:log_threads=1\n");
703       Report(
704           "HINT: LeakSanitizer does not work under ptrace (strace, gdb, "
705           "etc)\n");
706       Die();
707     }
708     // No new suppressions stacks, so rerun will not help and we can report.
709     if (!param.leak_report.ApplySuppressions())
710       return PrintResults(param.leak_report);
711 
712     // No indirect leaks to report, so we are done here.
713     if (!param.leak_report.IndirectUnsuppressedLeakCount())
714       return PrintResults(param.leak_report);
715 
716     if (i >= 8) {
717       Report("WARNING: LeakSanitizer gave up on indirect leaks suppression.\n");
718       return PrintResults(param.leak_report);
719     }
720 
721     // We found a new previously unseen suppressed call stack. Rerun to make
722     // sure it does not hold indirect leaks.
723     VReport(1, "Rerun with %zu suppressed stacks.",
724             GetSuppressionContext()->GetSortedSuppressedStacks().size());
725   }
726 }
727 
728 static bool has_reported_leaks = false;
729 bool HasReportedLeaks() { return has_reported_leaks; }
730 
731 void DoLeakCheck() {
732   Lock l(&global_mutex);
733   static bool already_done;
734   if (already_done) return;
735   already_done = true;
736   has_reported_leaks = CheckForLeaks();
737   if (has_reported_leaks) HandleLeaks();
738 }
739 
740 static int DoRecoverableLeakCheck() {
741   Lock l(&global_mutex);
742   bool have_leaks = CheckForLeaks();
743   return have_leaks ? 1 : 0;
744 }
745 
746 void DoRecoverableLeakCheckVoid() { DoRecoverableLeakCheck(); }
747 
748 Suppression *LeakSuppressionContext::GetSuppressionForAddr(uptr addr) {
749   Suppression *s = nullptr;
750 
751   // Suppress by module name.
752   if (const char *module_name =
753           Symbolizer::GetOrInit()->GetModuleNameForPc(addr))
754     if (context.Match(module_name, kSuppressionLeak, &s))
755       return s;
756 
757   // Suppress by file or function name.
758   SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
759   for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
760     if (context.Match(cur->info.function, kSuppressionLeak, &s) ||
761         context.Match(cur->info.file, kSuppressionLeak, &s)) {
762       break;
763     }
764   }
765   frames->ClearAll();
766   return s;
767 }
768 
769 Suppression *LeakSuppressionContext::GetSuppressionForStack(
770     u32 stack_trace_id, const StackTrace &stack) {
771   LazyInit();
772   for (uptr i = 0; i < stack.size; i++) {
773     Suppression *s = GetSuppressionForAddr(
774         StackTrace::GetPreviousInstructionPc(stack.trace[i]));
775     if (s) {
776       suppressed_stacks_sorted = false;
777       suppressed_stacks.push_back(stack_trace_id);
778       return s;
779     }
780   }
781   return nullptr;
782 }
783 
784 ///// LeakReport implementation. /////
785 
786 // A hard limit on the number of distinct leaks, to avoid quadratic complexity
787 // in LeakReport::AddLeakedChunk(). We don't expect to ever see this many leaks
788 // in real-world applications.
789 // FIXME: Get rid of this limit by changing the implementation of LeakReport to
790 // use a hash table.
791 const uptr kMaxLeaksConsidered = 5000;
792 
793 void LeakReport::AddLeakedChunk(uptr chunk, u32 stack_trace_id,
794                                 uptr leaked_size, ChunkTag tag) {
795   CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
796 
797   if (u32 resolution = flags()->resolution) {
798     StackTrace stack = stack_depot_.Get(stack_trace_id);
799     stack.size = Min(stack.size, resolution);
800     stack_trace_id = StackDepotPut(stack);
801   }
802 
803   bool is_directly_leaked = (tag == kDirectlyLeaked);
804   uptr i;
805   for (i = 0; i < leaks_.size(); i++) {
806     if (leaks_[i].stack_trace_id == stack_trace_id &&
807         leaks_[i].is_directly_leaked == is_directly_leaked) {
808       leaks_[i].hit_count++;
809       leaks_[i].total_size += leaked_size;
810       break;
811     }
812   }
813   if (i == leaks_.size()) {
814     if (leaks_.size() == kMaxLeaksConsidered) return;
815     Leak leak = { next_id_++, /* hit_count */ 1, leaked_size, stack_trace_id,
816                   is_directly_leaked, /* is_suppressed */ false };
817     leaks_.push_back(leak);
818   }
819   if (flags()->report_objects) {
820     LeakedObject obj = {leaks_[i].id, chunk, leaked_size};
821     leaked_objects_.push_back(obj);
822   }
823 }
824 
825 static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
826   if (leak1.is_directly_leaked == leak2.is_directly_leaked)
827     return leak1.total_size > leak2.total_size;
828   else
829     return leak1.is_directly_leaked;
830 }
831 
832 void LeakReport::ReportTopLeaks(uptr num_leaks_to_report) {
833   CHECK(leaks_.size() <= kMaxLeaksConsidered);
834   Printf("\n");
835   if (leaks_.size() == kMaxLeaksConsidered)
836     Printf("Too many leaks! Only the first %zu leaks encountered will be "
837            "reported.\n",
838            kMaxLeaksConsidered);
839 
840   uptr unsuppressed_count = UnsuppressedLeakCount();
841   if (num_leaks_to_report > 0 && num_leaks_to_report < unsuppressed_count)
842     Printf("The %zu top leak(s):\n", num_leaks_to_report);
843   Sort(leaks_.data(), leaks_.size(), &LeakComparator);
844   uptr leaks_reported = 0;
845   for (uptr i = 0; i < leaks_.size(); i++) {
846     if (leaks_[i].is_suppressed) continue;
847     PrintReportForLeak(i);
848     leaks_reported++;
849     if (leaks_reported == num_leaks_to_report) break;
850   }
851   if (leaks_reported < unsuppressed_count) {
852     uptr remaining = unsuppressed_count - leaks_reported;
853     Printf("Omitting %zu more leak(s).\n", remaining);
854   }
855 }
856 
857 void LeakReport::PrintReportForLeak(uptr index) {
858   Decorator d;
859   Printf("%s", d.Leak());
860   Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
861          leaks_[index].is_directly_leaked ? "Direct" : "Indirect",
862          leaks_[index].total_size, leaks_[index].hit_count);
863   Printf("%s", d.Default());
864 
865   CHECK(leaks_[index].stack_trace_id);
866   stack_depot_.Get(leaks_[index].stack_trace_id).Print();
867 
868   if (flags()->report_objects) {
869     Printf("Objects leaked above:\n");
870     PrintLeakedObjectsForLeak(index);
871     Printf("\n");
872   }
873 }
874 
875 void LeakReport::PrintLeakedObjectsForLeak(uptr index) {
876   u32 leak_id = leaks_[index].id;
877   for (uptr j = 0; j < leaked_objects_.size(); j++) {
878     if (leaked_objects_[j].leak_id == leak_id)
879       Printf("%p (%zu bytes)\n", leaked_objects_[j].addr,
880              leaked_objects_[j].size);
881   }
882 }
883 
884 void LeakReport::PrintSummary() {
885   CHECK(leaks_.size() <= kMaxLeaksConsidered);
886   uptr bytes = 0, allocations = 0;
887   for (uptr i = 0; i < leaks_.size(); i++) {
888       if (leaks_[i].is_suppressed) continue;
889       bytes += leaks_[i].total_size;
890       allocations += leaks_[i].hit_count;
891   }
892   InternalScopedString summary;
893   summary.append("%zu byte(s) leaked in %zu allocation(s).", bytes,
894                  allocations);
895   ReportErrorSummary(summary.data());
896 }
897 
898 uptr LeakReport::ApplySuppressions() {
899   LeakSuppressionContext *suppressions = GetSuppressionContext();
900   uptr new_suppressions = false;
901   for (uptr i = 0; i < leaks_.size(); i++) {
902     Suppression *s = suppressions->GetSuppressionForStack(
903         leaks_[i].stack_trace_id, stack_depot_.Get(leaks_[i].stack_trace_id));
904     if (s) {
905       s->weight += leaks_[i].total_size;
906       atomic_store_relaxed(&s->hit_count, atomic_load_relaxed(&s->hit_count) +
907           leaks_[i].hit_count);
908       leaks_[i].is_suppressed = true;
909       ++new_suppressions;
910     }
911   }
912   return new_suppressions;
913 }
914 
915 uptr LeakReport::UnsuppressedLeakCount() {
916   uptr result = 0;
917   for (uptr i = 0; i < leaks_.size(); i++)
918     if (!leaks_[i].is_suppressed) result++;
919   return result;
920 }
921 
922 uptr LeakReport::IndirectUnsuppressedLeakCount() {
923   uptr result = 0;
924   for (uptr i = 0; i < leaks_.size(); i++)
925     if (!leaks_[i].is_suppressed && !leaks_[i].is_directly_leaked)
926       result++;
927   return result;
928 }
929 
930 } // namespace __lsan
931 #else // CAN_SANITIZE_LEAKS
932 namespace __lsan {
933 void InitCommonLsan() { }
934 void DoLeakCheck() { }
935 void DoRecoverableLeakCheckVoid() { }
936 void DisableInThisThread() { }
937 void EnableInThisThread() { }
938 }
939 #endif // CAN_SANITIZE_LEAKS
940 
941 using namespace __lsan;
942 
943 extern "C" {
944 SANITIZER_INTERFACE_ATTRIBUTE
945 void __lsan_ignore_object(const void *p) {
946 #if CAN_SANITIZE_LEAKS
947   if (!common_flags()->detect_leaks)
948     return;
949   // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
950   // locked.
951   Lock l(&global_mutex);
952   IgnoreObjectResult res = IgnoreObjectLocked(p);
953   if (res == kIgnoreObjectInvalid)
954     VReport(1, "__lsan_ignore_object(): no heap object found at %p", p);
955   if (res == kIgnoreObjectAlreadyIgnored)
956     VReport(1, "__lsan_ignore_object(): "
957            "heap object at %p is already being ignored\n", p);
958   if (res == kIgnoreObjectSuccess)
959     VReport(1, "__lsan_ignore_object(): ignoring heap object at %p\n", p);
960 #endif // CAN_SANITIZE_LEAKS
961 }
962 
963 SANITIZER_INTERFACE_ATTRIBUTE
964 void __lsan_register_root_region(const void *begin, uptr size) {
965 #if CAN_SANITIZE_LEAKS
966   Lock l(&global_mutex);
967   CHECK(root_regions);
968   RootRegion region = {reinterpret_cast<uptr>(begin), size};
969   root_regions->push_back(region);
970   VReport(1, "Registered root region at %p of size %llu\n", begin, size);
971 #endif // CAN_SANITIZE_LEAKS
972 }
973 
974 SANITIZER_INTERFACE_ATTRIBUTE
975 void __lsan_unregister_root_region(const void *begin, uptr size) {
976 #if CAN_SANITIZE_LEAKS
977   Lock l(&global_mutex);
978   CHECK(root_regions);
979   bool removed = false;
980   for (uptr i = 0; i < root_regions->size(); i++) {
981     RootRegion region = (*root_regions)[i];
982     if (region.begin == reinterpret_cast<uptr>(begin) && region.size == size) {
983       removed = true;
984       uptr last_index = root_regions->size() - 1;
985       (*root_regions)[i] = (*root_regions)[last_index];
986       root_regions->pop_back();
987       VReport(1, "Unregistered root region at %p of size %llu\n", begin, size);
988       break;
989     }
990   }
991   if (!removed) {
992     Report(
993         "__lsan_unregister_root_region(): region at %p of size %llu has not "
994         "been registered.\n",
995         begin, size);
996     Die();
997   }
998 #endif // CAN_SANITIZE_LEAKS
999 }
1000 
1001 SANITIZER_INTERFACE_ATTRIBUTE
1002 void __lsan_disable() {
1003 #if CAN_SANITIZE_LEAKS
1004   __lsan::DisableInThisThread();
1005 #endif
1006 }
1007 
1008 SANITIZER_INTERFACE_ATTRIBUTE
1009 void __lsan_enable() {
1010 #if CAN_SANITIZE_LEAKS
1011   __lsan::EnableInThisThread();
1012 #endif
1013 }
1014 
1015 SANITIZER_INTERFACE_ATTRIBUTE
1016 void __lsan_do_leak_check() {
1017 #if CAN_SANITIZE_LEAKS
1018   if (common_flags()->detect_leaks)
1019     __lsan::DoLeakCheck();
1020 #endif // CAN_SANITIZE_LEAKS
1021 }
1022 
1023 SANITIZER_INTERFACE_ATTRIBUTE
1024 int __lsan_do_recoverable_leak_check() {
1025 #if CAN_SANITIZE_LEAKS
1026   if (common_flags()->detect_leaks)
1027     return __lsan::DoRecoverableLeakCheck();
1028 #endif // CAN_SANITIZE_LEAKS
1029   return 0;
1030 }
1031 
1032 SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_options, void) {
1033   return "";
1034 }
1035 
1036 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
1037 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1038 int __lsan_is_turned_off() {
1039   return 0;
1040 }
1041 
1042 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1043 const char *__lsan_default_suppressions() {
1044   return "";
1045 }
1046 #endif
1047 } // extern "C"
1048