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