Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp
35234 views
//===-- asan_malloc_linux.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of AddressSanitizer, an address sanity checker.9//10// Linux-specific malloc interception.11// We simply define functions like malloc, free, realloc, etc.12// They will replace the corresponding libc functions automagically.13//===----------------------------------------------------------------------===//1415#include "sanitizer_common/sanitizer_platform.h"16#if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \17SANITIZER_NETBSD || SANITIZER_SOLARIS1819# include "asan_allocator.h"20# include "asan_interceptors.h"21# include "asan_internal.h"22# include "asan_stack.h"23# include "lsan/lsan_common.h"24# include "sanitizer_common/sanitizer_allocator_checks.h"25# include "sanitizer_common/sanitizer_allocator_dlsym.h"26# include "sanitizer_common/sanitizer_errno.h"27# include "sanitizer_common/sanitizer_tls_get_addr.h"2829// ---------------------- Replacement functions ---------------- {{{130using namespace __asan;3132struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {33static bool UseImpl() { return !TryAsanInitFromRtl(); }34static void OnAllocate(const void *ptr, uptr size) {35# if CAN_SANITIZE_LEAKS36// Suppress leaks from dlerror(). Previously dlsym hack on global array was37// used by leak sanitizer as a root region.38__lsan_register_root_region(ptr, size);39# endif40}41static void OnFree(const void *ptr, uptr size) {42# if CAN_SANITIZE_LEAKS43__lsan_unregister_root_region(ptr, size);44# endif45}46};4748INTERCEPTOR(void, free, void *ptr) {49if (DlsymAlloc::PointerIsMine(ptr))50return DlsymAlloc::Free(ptr);51GET_STACK_TRACE_FREE;52asan_free(ptr, &stack, FROM_MALLOC);53}5455#if SANITIZER_INTERCEPT_CFREE56INTERCEPTOR(void, cfree, void *ptr) {57if (DlsymAlloc::PointerIsMine(ptr))58return DlsymAlloc::Free(ptr);59GET_STACK_TRACE_FREE;60asan_free(ptr, &stack, FROM_MALLOC);61}62#endif // SANITIZER_INTERCEPT_CFREE6364INTERCEPTOR(void*, malloc, uptr size) {65if (DlsymAlloc::Use())66return DlsymAlloc::Allocate(size);67GET_STACK_TRACE_MALLOC;68return asan_malloc(size, &stack);69}7071INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {72if (DlsymAlloc::Use())73return DlsymAlloc::Callocate(nmemb, size);74GET_STACK_TRACE_MALLOC;75return asan_calloc(nmemb, size, &stack);76}7778INTERCEPTOR(void*, realloc, void *ptr, uptr size) {79if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))80return DlsymAlloc::Realloc(ptr, size);81GET_STACK_TRACE_MALLOC;82return asan_realloc(ptr, size, &stack);83}8485#if SANITIZER_INTERCEPT_REALLOCARRAY86INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {87AsanInitFromRtl();88GET_STACK_TRACE_MALLOC;89return asan_reallocarray(ptr, nmemb, size, &stack);90}91#endif // SANITIZER_INTERCEPT_REALLOCARRAY9293#if SANITIZER_INTERCEPT_MEMALIGN94INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {95GET_STACK_TRACE_MALLOC;96return asan_memalign(boundary, size, &stack, FROM_MALLOC);97}9899INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {100GET_STACK_TRACE_MALLOC;101void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);102DTLS_on_libc_memalign(res, size);103return res;104}105#endif // SANITIZER_INTERCEPT_MEMALIGN106107#if SANITIZER_INTERCEPT_ALIGNED_ALLOC108INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {109GET_STACK_TRACE_MALLOC;110return asan_aligned_alloc(boundary, size, &stack);111}112#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC113114INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {115GET_CURRENT_PC_BP_SP;116(void)sp;117return asan_malloc_usable_size(ptr, pc, bp);118}119120#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO121// We avoid including malloc.h for portability reasons.122// man mallinfo says the fields are "long", but the implementation uses int.123// It doesn't matter much -- we just need to make sure that the libc's mallinfo124// is not called.125struct fake_mallinfo {126int x[10];127};128129INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {130struct fake_mallinfo res;131REAL(memset)(&res, 0, sizeof(res));132return res;133}134135INTERCEPTOR(int, mallopt, int cmd, int value) {136return 0;137}138#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO139140INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {141GET_STACK_TRACE_MALLOC;142return asan_posix_memalign(memptr, alignment, size, &stack);143}144145INTERCEPTOR(void*, valloc, uptr size) {146GET_STACK_TRACE_MALLOC;147return asan_valloc(size, &stack);148}149150#if SANITIZER_INTERCEPT_PVALLOC151INTERCEPTOR(void*, pvalloc, uptr size) {152GET_STACK_TRACE_MALLOC;153return asan_pvalloc(size, &stack);154}155#endif // SANITIZER_INTERCEPT_PVALLOC156157INTERCEPTOR(void, malloc_stats, void) {158__asan_print_accumulated_stats();159}160161#if SANITIZER_ANDROID162// Format of __libc_malloc_dispatch has changed in Android L.163// While we are moving towards a solution that does not depend on bionic164// internals, here is something to support both K* and L releases.165struct MallocDebugK {166void *(*malloc)(uptr bytes);167void (*free)(void *mem);168void *(*calloc)(uptr n_elements, uptr elem_size);169void *(*realloc)(void *oldMem, uptr bytes);170void *(*memalign)(uptr alignment, uptr bytes);171uptr (*malloc_usable_size)(void *mem);172};173174struct MallocDebugL {175void *(*calloc)(uptr n_elements, uptr elem_size);176void (*free)(void *mem);177fake_mallinfo (*mallinfo)(void);178void *(*malloc)(uptr bytes);179uptr (*malloc_usable_size)(void *mem);180void *(*memalign)(uptr alignment, uptr bytes);181int (*posix_memalign)(void **memptr, uptr alignment, uptr size);182void* (*pvalloc)(uptr size);183void *(*realloc)(void *oldMem, uptr bytes);184void* (*valloc)(uptr size);185};186187alignas(32) const MallocDebugK asan_malloc_dispatch_k = {188WRAP(malloc), WRAP(free), WRAP(calloc),189WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};190191alignas(32) const MallocDebugL asan_malloc_dispatch_l = {192WRAP(calloc), WRAP(free), WRAP(mallinfo),193WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign),194WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc),195WRAP(valloc)};196197namespace __asan {198void ReplaceSystemMalloc() {199void **__libc_malloc_dispatch_p =200(void **)AsanDlSymNext("__libc_malloc_dispatch");201if (__libc_malloc_dispatch_p) {202// Decide on K vs L dispatch format by the presence of203// __libc_malloc_default_dispatch export in libc.204void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");205if (default_dispatch_p)206*__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;207else208*__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;209}210}211} // namespace __asan212213#else // SANITIZER_ANDROID214215namespace __asan {216void ReplaceSystemMalloc() {217}218} // namespace __asan219#endif // SANITIZER_ANDROID220221#endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX ||222// SANITIZER_NETBSD || SANITIZER_SOLARIS223224225