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