xref: /freebsd/contrib/llvm-project/compiler-rt/lib/lsan/lsan_interceptors.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //=-- lsan_interceptors.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 // Interceptors for standalone LSan.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "interception/interception.h"
15 #include "sanitizer_common/sanitizer_allocator.h"
16 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
17 #include "sanitizer_common/sanitizer_allocator_report.h"
18 #include "sanitizer_common/sanitizer_atomic.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 #include "sanitizer_common/sanitizer_flags.h"
21 #include "sanitizer_common/sanitizer_internal_defs.h"
22 #include "sanitizer_common/sanitizer_linux.h"
23 #include "sanitizer_common/sanitizer_platform_interceptors.h"
24 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
25 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
26 #if SANITIZER_POSIX
27 #include "sanitizer_common/sanitizer_posix.h"
28 #endif
29 #include "lsan.h"
30 #include "lsan_allocator.h"
31 #include "lsan_common.h"
32 #include "lsan_thread.h"
33 
34 #include <stddef.h>
35 
36 using namespace __lsan;
37 
38 extern "C" {
39 int pthread_attr_init(void *attr);
40 int pthread_attr_destroy(void *attr);
41 int pthread_attr_getdetachstate(void *attr, int *v);
42 int pthread_key_create(unsigned *key, void (*destructor)(void* v));
43 int pthread_setspecific(unsigned key, const void *v);
44 }
45 
46 struct DlsymAlloc : DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc47   static bool UseImpl() { return lsan_init_is_running; }
OnAllocateDlsymAlloc48   static void OnAllocate(const void *ptr, uptr size) {
49 #if CAN_SANITIZE_LEAKS
50     // Suppress leaks from dlerror(). Previously dlsym hack on global array was
51     // used by leak sanitizer as a root region.
52     __lsan_register_root_region(ptr, size);
53 #endif
54   }
OnFreeDlsymAlloc55   static void OnFree(const void *ptr, uptr size) {
56 #if CAN_SANITIZE_LEAKS
57     __lsan_unregister_root_region(ptr, size);
58 #endif
59   }
60 };
61 
62 ///// Malloc/free interceptors. /////
63 
64 namespace std {
65   struct nothrow_t;
66   enum class align_val_t: size_t;
67 }
68 
69 #if !SANITIZER_APPLE
INTERCEPTOR(void *,malloc,uptr size)70 INTERCEPTOR(void*, malloc, uptr size) {
71   if (DlsymAlloc::Use())
72     return DlsymAlloc::Allocate(size);
73   ENSURE_LSAN_INITED;
74   GET_STACK_TRACE_MALLOC;
75   return lsan_malloc(size, stack);
76 }
77 
INTERCEPTOR(void,free,void * p)78 INTERCEPTOR(void, free, void *p) {
79   if (UNLIKELY(!p))
80     return;
81   if (DlsymAlloc::PointerIsMine(p))
82     return DlsymAlloc::Free(p);
83   ENSURE_LSAN_INITED;
84   lsan_free(p);
85 }
86 
87 #  if SANITIZER_INTERCEPT_FREE_SIZED
INTERCEPTOR(void,free_sized,void * p,uptr size)88 INTERCEPTOR(void, free_sized, void *p, uptr size) {
89   if (UNLIKELY(!p))
90     return;
91   if (DlsymAlloc::PointerIsMine(p))
92     return DlsymAlloc::Free(p);
93   ENSURE_LSAN_INITED;
94   lsan_free_sized(p, size);
95 }
96 #    define LSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
97 #  else
98 #    define LSAN_MAYBE_INTERCEPT_FREE_SIZED
99 #  endif
100 
101 #  if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
INTERCEPTOR(void,free_aligned_sized,void * p,uptr alignment,uptr size)102 INTERCEPTOR(void, free_aligned_sized, void *p, uptr alignment, uptr size) {
103   if (UNLIKELY(!p))
104     return;
105   if (DlsymAlloc::PointerIsMine(p))
106     return DlsymAlloc::Free(p);
107   ENSURE_LSAN_INITED;
108   lsan_free_aligned_sized(p, alignment, size);
109 }
110 #    define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
111       INTERCEPT_FUNCTION(free_aligned_sized)
112 #  else
113 #    define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
114 #  endif
115 
INTERCEPTOR(void *,calloc,uptr nmemb,uptr size)116 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
117   if (DlsymAlloc::Use())
118     return DlsymAlloc::Callocate(nmemb, size);
119   ENSURE_LSAN_INITED;
120   GET_STACK_TRACE_MALLOC;
121   return lsan_calloc(nmemb, size, stack);
122 }
123 
INTERCEPTOR(void *,realloc,void * ptr,uptr size)124 INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
125   if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
126     return DlsymAlloc::Realloc(ptr, size);
127   ENSURE_LSAN_INITED;
128   GET_STACK_TRACE_MALLOC;
129   return lsan_realloc(ptr, size, stack);
130 }
131 
INTERCEPTOR(void *,reallocarray,void * q,uptr nmemb,uptr size)132 INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
133   ENSURE_LSAN_INITED;
134   GET_STACK_TRACE_MALLOC;
135   return lsan_reallocarray(q, nmemb, size, stack);
136 }
137 
INTERCEPTOR(int,posix_memalign,void ** memptr,uptr alignment,uptr size)138 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
139   ENSURE_LSAN_INITED;
140   GET_STACK_TRACE_MALLOC;
141   return lsan_posix_memalign(memptr, alignment, size, stack);
142 }
143 
INTERCEPTOR(void *,valloc,uptr size)144 INTERCEPTOR(void*, valloc, uptr size) {
145   ENSURE_LSAN_INITED;
146   GET_STACK_TRACE_MALLOC;
147   return lsan_valloc(size, stack);
148 }
149 #else
150 #  define LSAN_MAYBE_INTERCEPT_FREE_SIZED
151 #  define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
152 #endif  // !SANITIZER_APPLE
153 
154 #if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void *,memalign,uptr alignment,uptr size)155 INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
156   ENSURE_LSAN_INITED;
157   GET_STACK_TRACE_MALLOC;
158   return lsan_memalign(alignment, size, stack);
159 }
160 #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
161 #else
162 #define LSAN_MAYBE_INTERCEPT_MEMALIGN
163 #endif  // SANITIZER_INTERCEPT_MEMALIGN
164 
165 #if SANITIZER_INTERCEPT___LIBC_MEMALIGN
INTERCEPTOR(void *,__libc_memalign,uptr alignment,uptr size)166 INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
167   ENSURE_LSAN_INITED;
168   GET_STACK_TRACE_MALLOC;
169   return lsan_memalign(alignment, size, stack);
170 }
171 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
172 #else
173 #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
174 #endif  // SANITIZER_INTERCEPT___LIBC_MEMALIGN
175 
176 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
INTERCEPTOR(void *,aligned_alloc,uptr alignment,uptr size)177 INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
178   ENSURE_LSAN_INITED;
179   GET_STACK_TRACE_MALLOC;
180   return lsan_aligned_alloc(alignment, size, stack);
181 }
182 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
183 #else
184 #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
185 #endif
186 
187 #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)188 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
189   ENSURE_LSAN_INITED;
190   return GetMallocUsableSize(ptr);
191 }
192 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
193         INTERCEPT_FUNCTION(malloc_usable_size)
194 #else
195 #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
196 #endif
197 
198 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
199 struct fake_mallinfo {
200   int x[10];
201 };
202 
INTERCEPTOR(struct fake_mallinfo,mallinfo,void)203 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
204   struct fake_mallinfo res;
205   internal_memset(&res, 0, sizeof(res));
206   return res;
207 }
208 #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
209 
INTERCEPTOR(int,mallopt,int cmd,int value)210 INTERCEPTOR(int, mallopt, int cmd, int value) {
211   return 0;
212 }
213 #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
214 #else
215 #define LSAN_MAYBE_INTERCEPT_MALLINFO
216 #define LSAN_MAYBE_INTERCEPT_MALLOPT
217 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
218 
219 #if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void *,pvalloc,uptr size)220 INTERCEPTOR(void*, pvalloc, uptr size) {
221   ENSURE_LSAN_INITED;
222   GET_STACK_TRACE_MALLOC;
223   return lsan_pvalloc(size, stack);
224 }
225 #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
226 #else
227 #define LSAN_MAYBE_INTERCEPT_PVALLOC
228 #endif // SANITIZER_INTERCEPT_PVALLOC
229 
230 #if SANITIZER_INTERCEPT_CFREE
231 INTERCEPTOR(void, cfree, void *p) ALIAS(WRAP(free));
232 #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
233 #else
234 #define LSAN_MAYBE_INTERCEPT_CFREE
235 #endif // SANITIZER_INTERCEPT_CFREE
236 
237 #if SANITIZER_INTERCEPT_MCHECK_MPROBE
INTERCEPTOR(int,mcheck,void (* abortfunc)(int mstatus))238 INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
239   return 0;
240 }
241 
INTERCEPTOR(int,mcheck_pedantic,void (* abortfunc)(int mstatus))242 INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
243   return 0;
244 }
245 
INTERCEPTOR(int,mprobe,void * ptr)246 INTERCEPTOR(int, mprobe, void *ptr) {
247   return 0;
248 }
249 #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
250 
251 
252 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
253 #define OPERATOR_NEW_BODY(nothrow)\
254   ENSURE_LSAN_INITED;\
255   GET_STACK_TRACE_MALLOC;\
256   void *res = lsan_malloc(size, stack);\
257   if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
258   return res;
259 #define OPERATOR_NEW_BODY_ALIGN(nothrow)\
260   ENSURE_LSAN_INITED;\
261   GET_STACK_TRACE_MALLOC;\
262   void *res = lsan_memalign((uptr)align, size, stack);\
263   if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
264   return res;
265 
266 #define OPERATOR_DELETE_BODY\
267   ENSURE_LSAN_INITED;\
268   lsan_free(ptr);
269 
270 // On OS X it's not enough to just provide our own 'operator new' and
271 // 'operator delete' implementations, because they're going to be in the runtime
272 // dylib, and the main executable will depend on both the runtime dylib and
273 // libstdc++, each of has its implementation of new and delete.
274 // To make sure that C++ allocation/deallocation operators are overridden on
275 // OS X we need to intercept them using their mangled names.
276 #if !SANITIZER_APPLE
277 
278 INTERCEPTOR_ATTRIBUTE
operator new(size_t size)279 void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
280 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size)281 void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
282 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::nothrow_t const &)283 void *operator new(size_t size, std::nothrow_t const&)
284 { OPERATOR_NEW_BODY(true /*nothrow*/); }
285 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::nothrow_t const &)286 void *operator new[](size_t size, std::nothrow_t const&)
287 { OPERATOR_NEW_BODY(true /*nothrow*/); }
288 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align)289 void *operator new(size_t size, std::align_val_t align)
290 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
291 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align)292 void *operator new[](size_t size, std::align_val_t align)
293 { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
294 INTERCEPTOR_ATTRIBUTE
operator new(size_t size,std::align_val_t align,std::nothrow_t const &)295 void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
296 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
297 INTERCEPTOR_ATTRIBUTE
operator new[](size_t size,std::align_val_t align,std::nothrow_t const &)298 void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
299 { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
300 
301 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr)302 void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
303 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr)304 void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
305 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::nothrow_t const &)306 void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
307 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::nothrow_t const &)308 void operator delete[](void *ptr, std::nothrow_t const &)
309 { OPERATOR_DELETE_BODY; }
310 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size)311 void operator delete(void *ptr, size_t size) NOEXCEPT
312 { OPERATOR_DELETE_BODY; }
313 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size)314 void operator delete[](void *ptr, size_t size) NOEXCEPT
315 { OPERATOR_DELETE_BODY; }
316 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t)317 void operator delete(void *ptr, std::align_val_t) NOEXCEPT
318 { OPERATOR_DELETE_BODY; }
319 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t)320 void operator delete[](void *ptr, std::align_val_t) NOEXCEPT
321 { OPERATOR_DELETE_BODY; }
322 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,std::align_val_t,std::nothrow_t const &)323 void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&)
324 { OPERATOR_DELETE_BODY; }
325 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,std::align_val_t,std::nothrow_t const &)326 void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&)
327 { OPERATOR_DELETE_BODY; }
328 INTERCEPTOR_ATTRIBUTE
operator delete(void * ptr,size_t size,std::align_val_t)329 void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT
330 { OPERATOR_DELETE_BODY; }
331 INTERCEPTOR_ATTRIBUTE
operator delete[](void * ptr,size_t size,std::align_val_t)332 void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT
333 { OPERATOR_DELETE_BODY; }
334 
335 #else  // SANITIZER_APPLE
336 
INTERCEPTOR(void *,_Znwm,size_t size)337 INTERCEPTOR(void *, _Znwm, size_t size)
338 { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR(void *,_Znam,size_t size)339 INTERCEPTOR(void *, _Znam, size_t size)
340 { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR(void *,_ZnwmRKSt9nothrow_t,size_t size,std::nothrow_t const &)341 INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
342 { OPERATOR_NEW_BODY(true /*nothrow*/); }
INTERCEPTOR(void *,_ZnamRKSt9nothrow_t,size_t size,std::nothrow_t const &)343 INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
344 { OPERATOR_NEW_BODY(true /*nothrow*/); }
345 
INTERCEPTOR(void,_ZdlPv,void * ptr)346 INTERCEPTOR(void, _ZdlPv, void *ptr)
347 { OPERATOR_DELETE_BODY; }
INTERCEPTOR(void,_ZdaPv,void * ptr)348 INTERCEPTOR(void, _ZdaPv, void *ptr)
349 { OPERATOR_DELETE_BODY; }
INTERCEPTOR(void,_ZdlPvRKSt9nothrow_t,void * ptr,std::nothrow_t const &)350 INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
351 { OPERATOR_DELETE_BODY; }
INTERCEPTOR(void,_ZdaPvRKSt9nothrow_t,void * ptr,std::nothrow_t const &)352 INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
353 { OPERATOR_DELETE_BODY; }
354 
355 #endif  // !SANITIZER_APPLE
356 
357 
358 ///// Thread initialization and finalization. /////
359 
360 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA
361 static unsigned g_thread_finalize_key;
362 
thread_finalize(void * v)363 static void thread_finalize(void *v) {
364   uptr iter = (uptr)v;
365   if (iter > 1) {
366     if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
367       Report("LeakSanitizer: failed to set thread key.\n");
368       Die();
369     }
370     return;
371   }
372   ThreadFinish();
373 }
374 #endif
375 
376 #if SANITIZER_NETBSD
INTERCEPTOR(void,_lwp_exit)377 INTERCEPTOR(void, _lwp_exit) {
378   ENSURE_LSAN_INITED;
379   ThreadFinish();
380   REAL(_lwp_exit)();
381 }
382 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit)
383 #else
384 #define LSAN_MAYBE_INTERCEPT__LWP_EXIT
385 #endif
386 
387 #if SANITIZER_INTERCEPT_THR_EXIT
INTERCEPTOR(void,thr_exit,tid_t * state)388 INTERCEPTOR(void, thr_exit, tid_t *state) {
389   ENSURE_LSAN_INITED;
390   ThreadFinish();
391   REAL(thr_exit)(state);
392 }
393 #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit)
394 #else
395 #define LSAN_MAYBE_INTERCEPT_THR_EXIT
396 #endif
397 
398 #if SANITIZER_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)399 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
400             void *dso_handle) {
401   __lsan::ScopedInterceptorDisabler disabler;
402   return REAL(__cxa_atexit)(func, arg, dso_handle);
403 }
404 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
405 #else
406 #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
407 #endif
408 
409 #if SANITIZER_INTERCEPT_ATEXIT
INTERCEPTOR(int,atexit,void (* f)())410 INTERCEPTOR(int, atexit, void (*f)()) {
411   __lsan::ScopedInterceptorDisabler disabler;
412   return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
413 }
414 #define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
415 #else
416 #define LSAN_MAYBE_INTERCEPT_ATEXIT
417 #endif
418 
419 #if SANITIZER_INTERCEPT_PTHREAD_ATFORK
420 extern "C" {
421 extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
422                            void (*child)());
423 }
424 
INTERCEPTOR(int,pthread_atfork,void (* prepare)(),void (* parent)(),void (* child)())425 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
426             void (*child)()) {
427   __lsan::ScopedInterceptorDisabler disabler;
428   // REAL(pthread_atfork) cannot be called due to symbol indirections at least
429   // on NetBSD
430   return _pthread_atfork(prepare, parent, child);
431 }
432 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
433 #else
434 #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
435 #endif
436 
437 #if SANITIZER_INTERCEPT_STRERROR
INTERCEPTOR(char *,strerror,int errnum)438 INTERCEPTOR(char *, strerror, int errnum) {
439   __lsan::ScopedInterceptorDisabler disabler;
440   return REAL(strerror)(errnum);
441 }
442 #define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
443 #else
444 #define LSAN_MAYBE_INTERCEPT_STRERROR
445 #endif
446 
447 #if SANITIZER_POSIX
448 
449 template <bool Detached>
ThreadStartFunc(void * arg)450 static void *ThreadStartFunc(void *arg) {
451   u32 parent_tid = (uptr)arg;
452   uptr tid = ThreadCreate(parent_tid, Detached);
453   // Wait until the last iteration to maximize the chance that we are the last
454   // destructor to run.
455 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
456   if (pthread_setspecific(g_thread_finalize_key,
457                           (void*)GetPthreadDestructorIterations())) {
458     Report("LeakSanitizer: failed to set thread key.\n");
459     Die();
460   }
461 #  endif
462   ThreadStart(tid, GetTid());
463   auto self = GetThreadSelf();
464   auto args = GetThreadArgRetval().GetArgs(self);
465   void *retval = (*args.routine)(args.arg_retval);
466   GetThreadArgRetval().Finish(self, retval);
467   return retval;
468 }
469 
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)470 INTERCEPTOR(int, pthread_create, void *th, void *attr,
471             void *(*callback)(void *), void *param) {
472   ENSURE_LSAN_INITED;
473   EnsureMainThreadIDIsCorrect();
474 
475   bool detached = [attr]() {
476     int d = 0;
477     return attr && !pthread_attr_getdetachstate(attr, &d) && IsStateDetached(d);
478   }();
479 
480   __sanitizer_pthread_attr_t myattr;
481   if (!attr) {
482     pthread_attr_init(&myattr);
483     attr = &myattr;
484   }
485   AdjustStackSize(attr);
486   uptr this_tid = GetCurrentThreadId();
487   int result;
488   {
489     // Ignore all allocations made by pthread_create: thread stack/TLS may be
490     // stored by pthread for future reuse even after thread destruction, and
491     // the linked list it's stored in doesn't even hold valid pointers to the
492     // objects, the latter are calculated by obscure pointer arithmetic.
493     ScopedInterceptorDisabler disabler;
494     GetThreadArgRetval().Create(detached, {callback, param}, [&]() -> uptr {
495       result = REAL(pthread_create)(
496           th, attr, detached ? ThreadStartFunc<true> : ThreadStartFunc<false>,
497           (void *)this_tid);
498       return result ? 0 : *(uptr *)(th);
499     });
500   }
501   if (attr == &myattr)
502     pthread_attr_destroy(&myattr);
503   return result;
504 }
505 
INTERCEPTOR(int,pthread_join,void * thread,void ** retval)506 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
507   int result;
508   GetThreadArgRetval().Join((uptr)thread, [&]() {
509     result = REAL(pthread_join)(thread, retval);
510     return !result;
511   });
512   return result;
513 }
514 
INTERCEPTOR(int,pthread_detach,void * thread)515 INTERCEPTOR(int, pthread_detach, void *thread) {
516   int result;
517   GetThreadArgRetval().Detach((uptr)thread, [&]() {
518     result = REAL(pthread_detach)(thread);
519     return !result;
520   });
521   return result;
522 }
523 
INTERCEPTOR(void,pthread_exit,void * retval)524 INTERCEPTOR(void, pthread_exit, void *retval) {
525   GetThreadArgRetval().Finish(GetThreadSelf(), retval);
526   REAL(pthread_exit)(retval);
527 }
528 
529 #  if SANITIZER_INTERCEPT_TRYJOIN
INTERCEPTOR(int,pthread_tryjoin_np,void * thread,void ** ret)530 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
531   int result;
532   GetThreadArgRetval().Join((uptr)thread, [&]() {
533     result = REAL(pthread_tryjoin_np)(thread, ret);
534     return !result;
535   });
536   return result;
537 }
538 #    define LSAN_MAYBE_INTERCEPT_TRYJOIN INTERCEPT_FUNCTION(pthread_tryjoin_np)
539 #  else
540 #    define LSAN_MAYBE_INTERCEPT_TRYJOIN
541 #  endif  // SANITIZER_INTERCEPT_TRYJOIN
542 
543 #  if SANITIZER_INTERCEPT_TIMEDJOIN
INTERCEPTOR(int,pthread_timedjoin_np,void * thread,void ** ret,const struct timespec * abstime)544 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
545             const struct timespec *abstime) {
546   int result;
547   GetThreadArgRetval().Join((uptr)thread, [&]() {
548     result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
549     return !result;
550   });
551   return result;
552 }
553 #    define LSAN_MAYBE_INTERCEPT_TIMEDJOIN \
554       INTERCEPT_FUNCTION(pthread_timedjoin_np)
555 #  else
556 #    define LSAN_MAYBE_INTERCEPT_TIMEDJOIN
557 #  endif  // SANITIZER_INTERCEPT_TIMEDJOIN
558 
559 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
560 
INTERCEPTOR(void,_exit,int status)561 INTERCEPTOR(void, _exit, int status) {
562   if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode;
563   REAL(_exit)(status);
564 }
565 
566 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
567 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_LSAN_INITED
568 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
569 
570 #endif  // SANITIZER_POSIX
571 
572 namespace __lsan {
573 
InitializeInterceptors()574 void InitializeInterceptors() {
575   // Fuchsia doesn't use interceptors that require any setup.
576 #if !SANITIZER_FUCHSIA
577   __interception::DoesNotSupportStaticLinking();
578   InitializeSignalInterceptors();
579 
580   INTERCEPT_FUNCTION(malloc);
581   INTERCEPT_FUNCTION(free);
582   LSAN_MAYBE_INTERCEPT_FREE_SIZED;
583   LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
584   LSAN_MAYBE_INTERCEPT_CFREE;
585   INTERCEPT_FUNCTION(calloc);
586   INTERCEPT_FUNCTION(realloc);
587   LSAN_MAYBE_INTERCEPT_MEMALIGN;
588   LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
589   LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
590   INTERCEPT_FUNCTION(posix_memalign);
591   INTERCEPT_FUNCTION(valloc);
592   LSAN_MAYBE_INTERCEPT_PVALLOC;
593   LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
594   LSAN_MAYBE_INTERCEPT_MALLINFO;
595   LSAN_MAYBE_INTERCEPT_MALLOPT;
596   INTERCEPT_FUNCTION(pthread_create);
597   INTERCEPT_FUNCTION(pthread_join);
598   INTERCEPT_FUNCTION(pthread_detach);
599   INTERCEPT_FUNCTION(pthread_exit);
600   LSAN_MAYBE_INTERCEPT_TIMEDJOIN;
601   LSAN_MAYBE_INTERCEPT_TRYJOIN;
602   INTERCEPT_FUNCTION(_exit);
603 
604   LSAN_MAYBE_INTERCEPT__LWP_EXIT;
605   LSAN_MAYBE_INTERCEPT_THR_EXIT;
606 
607   LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
608   LSAN_MAYBE_INTERCEPT_ATEXIT;
609   LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
610 
611   LSAN_MAYBE_INTERCEPT_STRERROR;
612 
613 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
614   if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
615     Report("LeakSanitizer: failed to create thread key.\n");
616     Die();
617   }
618 #endif
619 
620 #endif  // !SANITIZER_FUCHSIA
621 }
622 
623 } // namespace __lsan
624