1//=-- lsan_interceptors.cc ------------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is a part of LeakSanitizer. 9// Interceptors for standalone LSan. 10// 11//===----------------------------------------------------------------------===// 12 13#include "interception/interception.h" 14#include "sanitizer_common/sanitizer_allocator.h" 15#include "sanitizer_common/sanitizer_allocator_report.h" 16#include "sanitizer_common/sanitizer_atomic.h" 17#include "sanitizer_common/sanitizer_common.h" 18#include "sanitizer_common/sanitizer_flags.h" 19#include "sanitizer_common/sanitizer_internal_defs.h" 20#include "sanitizer_common/sanitizer_linux.h" 21#include "sanitizer_common/sanitizer_platform_interceptors.h" 22#include "sanitizer_common/sanitizer_platform_limits_netbsd.h" 23#include "sanitizer_common/sanitizer_platform_limits_posix.h" 24#include "sanitizer_common/sanitizer_posix.h" 25#include "sanitizer_common/sanitizer_tls_get_addr.h" 26#include "lsan.h" 27#include "lsan_allocator.h" 28#include "lsan_common.h" 29#include "lsan_thread.h" 30 31#include <stddef.h> 32 33using namespace __lsan; 34 35extern "C" { 36int pthread_attr_init(void *attr); 37int pthread_attr_destroy(void *attr); 38int pthread_attr_getdetachstate(void *attr, int *v); 39int pthread_key_create(unsigned *key, void (*destructor)(void* v)); 40int pthread_setspecific(unsigned key, const void *v); 41} 42 43///// Malloc/free interceptors. ///// 44 45namespace std { 46 struct nothrow_t; 47 enum class align_val_t: size_t; 48} 49 50#if !SANITIZER_MAC 51INTERCEPTOR(void*, malloc, uptr size) { 52 ENSURE_LSAN_INITED; 53 GET_STACK_TRACE_MALLOC; 54 return lsan_malloc(size, stack); 55} 56 57INTERCEPTOR(void, free, void *p) { 58 ENSURE_LSAN_INITED; 59 lsan_free(p); 60} 61 62INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 63 if (lsan_init_is_running) { 64 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 65 const uptr kCallocPoolSize = 1024; 66 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 67 static uptr allocated; 68 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 69 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 70 allocated += size_in_words; 71 CHECK(allocated < kCallocPoolSize); 72 return mem; 73 } 74 ENSURE_LSAN_INITED; 75 GET_STACK_TRACE_MALLOC; 76 return lsan_calloc(nmemb, size, stack); 77} 78 79INTERCEPTOR(void*, realloc, void *q, uptr size) { 80 ENSURE_LSAN_INITED; 81 GET_STACK_TRACE_MALLOC; 82 return lsan_realloc(q, size, stack); 83} 84 85INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 86 ENSURE_LSAN_INITED; 87 GET_STACK_TRACE_MALLOC; 88 return lsan_posix_memalign(memptr, alignment, size, stack); 89} 90 91INTERCEPTOR(void*, valloc, uptr size) { 92 ENSURE_LSAN_INITED; 93 GET_STACK_TRACE_MALLOC; 94 return lsan_valloc(size, stack); 95} 96#endif 97 98#if SANITIZER_INTERCEPT_MEMALIGN 99INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { 100 ENSURE_LSAN_INITED; 101 GET_STACK_TRACE_MALLOC; 102 return lsan_memalign(alignment, size, stack); 103} 104#define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 105 106INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) { 107 ENSURE_LSAN_INITED; 108 GET_STACK_TRACE_MALLOC; 109 void *res = lsan_memalign(alignment, size, stack); 110 DTLS_on_libc_memalign(res, size); 111 return res; 112} 113#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 114#else 115#define LSAN_MAYBE_INTERCEPT_MEMALIGN 116#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 117#endif // SANITIZER_INTERCEPT_MEMALIGN 118 119#if SANITIZER_INTERCEPT_ALIGNED_ALLOC 120INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { 121 ENSURE_LSAN_INITED; 122 GET_STACK_TRACE_MALLOC; 123 return lsan_aligned_alloc(alignment, size, stack); 124} 125#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 126#else 127#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 128#endif 129 130#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE 131INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 132 ENSURE_LSAN_INITED; 133 return GetMallocUsableSize(ptr); 134} 135#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 136 INTERCEPT_FUNCTION(malloc_usable_size) 137#else 138#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 139#endif 140 141#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 142struct fake_mallinfo { 143 int x[10]; 144}; 145 146INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 147 struct fake_mallinfo res; 148 internal_memset(&res, 0, sizeof(res)); 149 return res; 150} 151#define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 152 153INTERCEPTOR(int, mallopt, int cmd, int value) { 154 return -1; 155} 156#define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 157#else 158#define LSAN_MAYBE_INTERCEPT_MALLINFO 159#define LSAN_MAYBE_INTERCEPT_MALLOPT 160#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 161 162#if SANITIZER_INTERCEPT_PVALLOC 163INTERCEPTOR(void*, pvalloc, uptr size) { 164 ENSURE_LSAN_INITED; 165 GET_STACK_TRACE_MALLOC; 166 return lsan_pvalloc(size, stack); 167} 168#define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 169#else 170#define LSAN_MAYBE_INTERCEPT_PVALLOC 171#endif // SANITIZER_INTERCEPT_PVALLOC 172 173#if SANITIZER_INTERCEPT_CFREE 174INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free)); 175#define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 176#else 177#define LSAN_MAYBE_INTERCEPT_CFREE 178#endif // SANITIZER_INTERCEPT_CFREE 179 180#if SANITIZER_INTERCEPT_MCHECK_MPROBE 181INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 182 return 0; 183} 184 185INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 186 return 0; 187} 188 189INTERCEPTOR(int, mprobe, void *ptr) { 190 return 0; 191} 192#endif // SANITIZER_INTERCEPT_MCHECK_MPROBE 193 194 195// TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 196#define OPERATOR_NEW_BODY(nothrow)\ 197 ENSURE_LSAN_INITED;\ 198 GET_STACK_TRACE_MALLOC;\ 199 void *res = lsan_malloc(size, stack);\ 200 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 201 return res; 202#define OPERATOR_NEW_BODY_ALIGN(nothrow)\ 203 ENSURE_LSAN_INITED;\ 204 GET_STACK_TRACE_MALLOC;\ 205 void *res = lsan_memalign((uptr)align, size, stack);\ 206 if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 207 return res; 208 209#define OPERATOR_DELETE_BODY\ 210 ENSURE_LSAN_INITED;\ 211 lsan_free(ptr); 212 213// On OS X it's not enough to just provide our own 'operator new' and 214// 'operator delete' implementations, because they're going to be in the runtime 215// dylib, and the main executable will depend on both the runtime dylib and 216// libstdc++, each of has its implementation of new and delete. 217// To make sure that C++ allocation/deallocation operators are overridden on 218// OS X we need to intercept them using their mangled names. 219#if !SANITIZER_MAC 220 221INTERCEPTOR_ATTRIBUTE 222void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 223INTERCEPTOR_ATTRIBUTE 224void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 225INTERCEPTOR_ATTRIBUTE 226void *operator new(size_t size, std::nothrow_t const&) 227{ OPERATOR_NEW_BODY(true /*nothrow*/); } 228INTERCEPTOR_ATTRIBUTE 229void *operator new[](size_t size, std::nothrow_t const&) 230{ OPERATOR_NEW_BODY(true /*nothrow*/); } 231INTERCEPTOR_ATTRIBUTE 232void *operator new(size_t size, std::align_val_t align) 233{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 234INTERCEPTOR_ATTRIBUTE 235void *operator new[](size_t size, std::align_val_t align) 236{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 237INTERCEPTOR_ATTRIBUTE 238void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 239{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 240INTERCEPTOR_ATTRIBUTE 241void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 242{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 243 244INTERCEPTOR_ATTRIBUTE 245void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 246INTERCEPTOR_ATTRIBUTE 247void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 248INTERCEPTOR_ATTRIBUTE 249void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 250INTERCEPTOR_ATTRIBUTE 251void operator delete[](void *ptr, std::nothrow_t const &) 252{ OPERATOR_DELETE_BODY; } 253INTERCEPTOR_ATTRIBUTE 254void operator delete(void *ptr, size_t size) NOEXCEPT 255{ OPERATOR_DELETE_BODY; } 256INTERCEPTOR_ATTRIBUTE 257void operator delete[](void *ptr, size_t size) NOEXCEPT 258{ OPERATOR_DELETE_BODY; } 259INTERCEPTOR_ATTRIBUTE 260void operator delete(void *ptr, std::align_val_t) NOEXCEPT 261{ OPERATOR_DELETE_BODY; } 262INTERCEPTOR_ATTRIBUTE 263void operator delete[](void *ptr, std::align_val_t) NOEXCEPT 264{ OPERATOR_DELETE_BODY; } 265INTERCEPTOR_ATTRIBUTE 266void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 267{ OPERATOR_DELETE_BODY; } 268INTERCEPTOR_ATTRIBUTE 269void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 270{ OPERATOR_DELETE_BODY; } 271INTERCEPTOR_ATTRIBUTE 272void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 273{ OPERATOR_DELETE_BODY; } 274INTERCEPTOR_ATTRIBUTE 275void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 276{ OPERATOR_DELETE_BODY; } 277 278#else // SANITIZER_MAC 279 280INTERCEPTOR(void *, _Znwm, size_t size) 281{ OPERATOR_NEW_BODY(false /*nothrow*/); } 282INTERCEPTOR(void *, _Znam, size_t size) 283{ OPERATOR_NEW_BODY(false /*nothrow*/); } 284INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 285{ OPERATOR_NEW_BODY(true /*nothrow*/); } 286INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 287{ OPERATOR_NEW_BODY(true /*nothrow*/); } 288 289INTERCEPTOR(void, _ZdlPv, void *ptr) 290{ OPERATOR_DELETE_BODY; } 291INTERCEPTOR(void, _ZdaPv, void *ptr) 292{ OPERATOR_DELETE_BODY; } 293INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 294{ OPERATOR_DELETE_BODY; } 295INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 296{ OPERATOR_DELETE_BODY; } 297 298#endif // !SANITIZER_MAC 299 300 301///// Thread initialization and finalization. ///// 302 303#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 304static unsigned g_thread_finalize_key; 305 306static void thread_finalize(void *v) { 307 uptr iter = (uptr)v; 308 if (iter > 1) { 309 if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 310 Report("LeakSanitizer: failed to set thread key.\n"); 311 Die(); 312 } 313 return; 314 } 315 ThreadFinish(); 316} 317#endif 318 319#if SANITIZER_NETBSD 320INTERCEPTOR(void, _lwp_exit) { 321 ENSURE_LSAN_INITED; 322 ThreadFinish(); 323 REAL(_lwp_exit)(); 324} 325#define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) 326#else 327#define LSAN_MAYBE_INTERCEPT__LWP_EXIT 328#endif 329 330#if SANITIZER_INTERCEPT_THR_EXIT 331INTERCEPTOR(void, thr_exit, tid_t *state) { 332 ENSURE_LSAN_INITED; 333 ThreadFinish(); 334 REAL(thr_exit)(state); 335} 336#define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit) 337#else 338#define LSAN_MAYBE_INTERCEPT_THR_EXIT 339#endif 340 341#if SANITIZER_INTERCEPT_STRERROR 342INTERCEPTOR(char *, strerror, int errnum) { 343 __lsan::ScopedInterceptorDisabler disabler; 344 return REAL(strerror)(errnum); 345} 346#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror) 347#else 348#define LSAN_MAYBE_INTERCEPT_STRERROR 349#endif 350 351#if SANITIZER_INTERCEPT___CXA_ATEXIT 352INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 353 void *dso_handle) { 354 __lsan::ScopedInterceptorDisabler disabler; 355 return REAL(__cxa_atexit)(func, arg, dso_handle); 356} 357#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) 358#else 359#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT 360#endif 361 362#if SANITIZER_INTERCEPT_ATEXIT 363INTERCEPTOR(int, atexit, void (*f)()) { 364 __lsan::ScopedInterceptorDisabler disabler; 365 return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); 366} 367#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) 368#else 369#define LSAN_MAYBE_INTERCEPT_ATEXIT 370#endif 371 372#if SANITIZER_INTERCEPT_PTHREAD_ATFORK 373extern "C" { 374extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 375 void (*child)()); 376}; 377 378INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 379 void (*child)()) { 380 __lsan::ScopedInterceptorDisabler disabler; 381 // REAL(pthread_atfork) cannot be called due to symbol indirections at least on NetBSD 382 return _pthread_atfork(prepare, parent, child); 383} 384#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) 385#else 386#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK 387#endif 388 389struct ThreadParam { 390 void *(*callback)(void *arg); 391 void *param; 392 atomic_uintptr_t tid; 393}; 394 395extern "C" void *__lsan_thread_start_func(void *arg) { 396 ThreadParam *p = (ThreadParam*)arg; 397 void* (*callback)(void *arg) = p->callback; 398 void *param = p->param; 399 // Wait until the last iteration to maximize the chance that we are the last 400 // destructor to run. 401#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 402 if (pthread_setspecific(g_thread_finalize_key, 403 (void*)GetPthreadDestructorIterations())) { 404 Report("LeakSanitizer: failed to set thread key.\n"); 405 Die(); 406 } 407#endif 408 int tid = 0; 409 while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) 410 internal_sched_yield(); 411 SetCurrentThread(tid); 412 ThreadStart(tid, GetTid()); 413 atomic_store(&p->tid, 0, memory_order_release); 414 return callback(param); 415} 416 417INTERCEPTOR(int, pthread_create, void *th, void *attr, 418 void *(*callback)(void *), void *param) { 419 ENSURE_LSAN_INITED; 420 EnsureMainThreadIDIsCorrect(); 421 __sanitizer_pthread_attr_t myattr; 422 if (!attr) { 423 pthread_attr_init(&myattr); 424 attr = &myattr; 425 } 426 AdjustStackSize(attr); 427 int detached = 0; 428 pthread_attr_getdetachstate(attr, &detached); 429 ThreadParam p; 430 p.callback = callback; 431 p.param = param; 432 atomic_store(&p.tid, 0, memory_order_relaxed); 433 int res; 434 { 435 // Ignore all allocations made by pthread_create: thread stack/TLS may be 436 // stored by pthread for future reuse even after thread destruction, and 437 // the linked list it's stored in doesn't even hold valid pointers to the 438 // objects, the latter are calculated by obscure pointer arithmetic. 439 ScopedInterceptorDisabler disabler; 440 res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p); 441 } 442 if (res == 0) { 443 int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th, 444 IsStateDetached(detached)); 445 CHECK_NE(tid, 0); 446 atomic_store(&p.tid, tid, memory_order_release); 447 while (atomic_load(&p.tid, memory_order_acquire) != 0) 448 internal_sched_yield(); 449 } 450 if (attr == &myattr) 451 pthread_attr_destroy(&myattr); 452 return res; 453} 454 455INTERCEPTOR(int, pthread_join, void *th, void **ret) { 456 ENSURE_LSAN_INITED; 457 int tid = ThreadTid((uptr)th); 458 int res = REAL(pthread_join)(th, ret); 459 if (res == 0) 460 ThreadJoin(tid); 461 return res; 462} 463 464INTERCEPTOR(void, _exit, int status) { 465 if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode; 466 REAL(_exit)(status); 467} 468 469#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 470#include "sanitizer_common/sanitizer_signal_interceptors.inc" 471 472namespace __lsan { 473 474void InitializeInterceptors() { 475 InitializeSignalInterceptors(); 476 477 INTERCEPT_FUNCTION(malloc); 478 INTERCEPT_FUNCTION(free); 479 LSAN_MAYBE_INTERCEPT_CFREE; 480 INTERCEPT_FUNCTION(calloc); 481 INTERCEPT_FUNCTION(realloc); 482 LSAN_MAYBE_INTERCEPT_MEMALIGN; 483 LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 484 LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 485 INTERCEPT_FUNCTION(posix_memalign); 486 INTERCEPT_FUNCTION(valloc); 487 LSAN_MAYBE_INTERCEPT_PVALLOC; 488 LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 489 LSAN_MAYBE_INTERCEPT_MALLINFO; 490 LSAN_MAYBE_INTERCEPT_MALLOPT; 491 INTERCEPT_FUNCTION(pthread_create); 492 INTERCEPT_FUNCTION(pthread_join); 493 INTERCEPT_FUNCTION(_exit); 494 495 LSAN_MAYBE_INTERCEPT__LWP_EXIT; 496 LSAN_MAYBE_INTERCEPT_THR_EXIT; 497 498 LSAN_MAYBE_INTERCEPT_STRERROR; 499 500 LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; 501 LSAN_MAYBE_INTERCEPT_ATEXIT; 502 LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; 503 504#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 505 if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 506 Report("LeakSanitizer: failed to create thread key.\n"); 507 Die(); 508 } 509#endif 510} 511 512} // namespace __lsan 513