1 //===-- asan_malloc_linux.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 AddressSanitizer, an address sanity checker. 10 // 11 // Linux-specific malloc interception. 12 // We simply define functions like malloc, free, realloc, etc. 13 // They will replace the corresponding libc functions automagically. 14 //===----------------------------------------------------------------------===// 15 16 #include "sanitizer_common/sanitizer_platform.h" 17 #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \ 18 SANITIZER_NETBSD || SANITIZER_SOLARIS 19 20 # include "asan_allocator.h" 21 # include "asan_interceptors.h" 22 # include "asan_internal.h" 23 # include "asan_stack.h" 24 # include "lsan/lsan_common.h" 25 # include "sanitizer_common/sanitizer_allocator_checks.h" 26 # include "sanitizer_common/sanitizer_allocator_dlsym.h" 27 # include "sanitizer_common/sanitizer_errno.h" 28 # include "sanitizer_common/sanitizer_tls_get_addr.h" 29 30 // ---------------------- Replacement functions ---------------- {{{1 31 using namespace __asan; 32 33 struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 34 static bool UseImpl() { return !TryAsanInitFromRtl(); } 35 static void OnAllocate(const void *ptr, uptr size) { 36 # if CAN_SANITIZE_LEAKS 37 // Suppress leaks from dlerror(). Previously dlsym hack on global array was 38 // used by leak sanitizer as a root region. 39 __lsan_register_root_region(ptr, size); 40 # endif 41 } 42 static void OnFree(const void *ptr, uptr size) { 43 # if CAN_SANITIZE_LEAKS 44 __lsan_unregister_root_region(ptr, size); 45 # endif 46 } 47 }; 48 49 INTERCEPTOR(void, free, void *ptr) { 50 if (DlsymAlloc::PointerIsMine(ptr)) 51 return DlsymAlloc::Free(ptr); 52 GET_STACK_TRACE_FREE; 53 asan_free(ptr, &stack, FROM_MALLOC); 54 } 55 56 #if SANITIZER_INTERCEPT_CFREE 57 INTERCEPTOR(void, cfree, void *ptr) { 58 if (DlsymAlloc::PointerIsMine(ptr)) 59 return DlsymAlloc::Free(ptr); 60 GET_STACK_TRACE_FREE; 61 asan_free(ptr, &stack, FROM_MALLOC); 62 } 63 #endif // SANITIZER_INTERCEPT_CFREE 64 65 INTERCEPTOR(void*, malloc, uptr size) { 66 if (DlsymAlloc::Use()) 67 return DlsymAlloc::Allocate(size); 68 GET_STACK_TRACE_MALLOC; 69 return asan_malloc(size, &stack); 70 } 71 72 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 73 if (DlsymAlloc::Use()) 74 return DlsymAlloc::Callocate(nmemb, size); 75 GET_STACK_TRACE_MALLOC; 76 return asan_calloc(nmemb, size, &stack); 77 } 78 79 INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 80 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 81 return DlsymAlloc::Realloc(ptr, size); 82 GET_STACK_TRACE_MALLOC; 83 return asan_realloc(ptr, size, &stack); 84 } 85 86 #if SANITIZER_INTERCEPT_REALLOCARRAY 87 INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) { 88 AsanInitFromRtl(); 89 GET_STACK_TRACE_MALLOC; 90 return asan_reallocarray(ptr, nmemb, size, &stack); 91 } 92 #endif // SANITIZER_INTERCEPT_REALLOCARRAY 93 94 #if SANITIZER_INTERCEPT_MEMALIGN 95 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 96 GET_STACK_TRACE_MALLOC; 97 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 98 } 99 100 INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { 101 GET_STACK_TRACE_MALLOC; 102 void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); 103 DTLS_on_libc_memalign(res, size); 104 return res; 105 } 106 #endif // SANITIZER_INTERCEPT_MEMALIGN 107 108 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 109 INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { 110 GET_STACK_TRACE_MALLOC; 111 return asan_aligned_alloc(boundary, size, &stack); 112 } 113 #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC 114 115 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 116 GET_CURRENT_PC_BP_SP; 117 (void)sp; 118 return asan_malloc_usable_size(ptr, pc, bp); 119 } 120 121 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 122 // We avoid including malloc.h for portability reasons. 123 // man mallinfo says the fields are "long", but the implementation uses int. 124 // It doesn't matter much -- we just need to make sure that the libc's mallinfo 125 // is not called. 126 struct fake_mallinfo { 127 int x[10]; 128 }; 129 130 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 131 struct fake_mallinfo res; 132 REAL(memset)(&res, 0, sizeof(res)); 133 return res; 134 } 135 136 INTERCEPTOR(int, mallopt, int cmd, int value) { 137 return 0; 138 } 139 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 140 141 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 142 GET_STACK_TRACE_MALLOC; 143 return asan_posix_memalign(memptr, alignment, size, &stack); 144 } 145 146 INTERCEPTOR(void*, valloc, uptr size) { 147 GET_STACK_TRACE_MALLOC; 148 return asan_valloc(size, &stack); 149 } 150 151 #if SANITIZER_INTERCEPT_PVALLOC 152 INTERCEPTOR(void*, pvalloc, uptr size) { 153 GET_STACK_TRACE_MALLOC; 154 return asan_pvalloc(size, &stack); 155 } 156 #endif // SANITIZER_INTERCEPT_PVALLOC 157 158 INTERCEPTOR(void, malloc_stats, void) { 159 __asan_print_accumulated_stats(); 160 } 161 162 #if SANITIZER_ANDROID 163 // Format of __libc_malloc_dispatch has changed in Android L. 164 // While we are moving towards a solution that does not depend on bionic 165 // internals, here is something to support both K* and L releases. 166 struct MallocDebugK { 167 void *(*malloc)(uptr bytes); 168 void (*free)(void *mem); 169 void *(*calloc)(uptr n_elements, uptr elem_size); 170 void *(*realloc)(void *oldMem, uptr bytes); 171 void *(*memalign)(uptr alignment, uptr bytes); 172 uptr (*malloc_usable_size)(void *mem); 173 }; 174 175 struct MallocDebugL { 176 void *(*calloc)(uptr n_elements, uptr elem_size); 177 void (*free)(void *mem); 178 fake_mallinfo (*mallinfo)(void); 179 void *(*malloc)(uptr bytes); 180 uptr (*malloc_usable_size)(void *mem); 181 void *(*memalign)(uptr alignment, uptr bytes); 182 int (*posix_memalign)(void **memptr, uptr alignment, uptr size); 183 void* (*pvalloc)(uptr size); 184 void *(*realloc)(void *oldMem, uptr bytes); 185 void* (*valloc)(uptr size); 186 }; 187 188 ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = { 189 WRAP(malloc), WRAP(free), WRAP(calloc), 190 WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; 191 192 ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = { 193 WRAP(calloc), WRAP(free), WRAP(mallinfo), 194 WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign), 195 WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc), 196 WRAP(valloc)}; 197 198 namespace __asan { 199 void ReplaceSystemMalloc() { 200 void **__libc_malloc_dispatch_p = 201 (void **)AsanDlSymNext("__libc_malloc_dispatch"); 202 if (__libc_malloc_dispatch_p) { 203 // Decide on K vs L dispatch format by the presence of 204 // __libc_malloc_default_dispatch export in libc. 205 void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch"); 206 if (default_dispatch_p) 207 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k; 208 else 209 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l; 210 } 211 } 212 } // namespace __asan 213 214 #else // SANITIZER_ANDROID 215 216 namespace __asan { 217 void ReplaceSystemMalloc() { 218 } 219 } // namespace __asan 220 #endif // SANITIZER_ANDROID 221 222 #endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || 223 // SANITIZER_NETBSD || SANITIZER_SOLARIS 224