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