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 asan_init_is_running; } 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 ENSURE_ASAN_INITED(); 69 GET_STACK_TRACE_MALLOC; 70 return asan_malloc(size, &stack); 71 } 72 73 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 74 if (DlsymAlloc::Use()) 75 return DlsymAlloc::Callocate(nmemb, size); 76 ENSURE_ASAN_INITED(); 77 GET_STACK_TRACE_MALLOC; 78 return asan_calloc(nmemb, size, &stack); 79 } 80 81 INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 82 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 83 return DlsymAlloc::Realloc(ptr, size); 84 ENSURE_ASAN_INITED(); 85 GET_STACK_TRACE_MALLOC; 86 return asan_realloc(ptr, size, &stack); 87 } 88 89 #if SANITIZER_INTERCEPT_REALLOCARRAY 90 INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) { 91 ENSURE_ASAN_INITED(); 92 GET_STACK_TRACE_MALLOC; 93 return asan_reallocarray(ptr, nmemb, size, &stack); 94 } 95 #endif // SANITIZER_INTERCEPT_REALLOCARRAY 96 97 #if SANITIZER_INTERCEPT_MEMALIGN 98 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 99 GET_STACK_TRACE_MALLOC; 100 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 101 } 102 103 INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { 104 GET_STACK_TRACE_MALLOC; 105 void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); 106 DTLS_on_libc_memalign(res, size); 107 return res; 108 } 109 #endif // SANITIZER_INTERCEPT_MEMALIGN 110 111 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 112 INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { 113 GET_STACK_TRACE_MALLOC; 114 return asan_aligned_alloc(boundary, size, &stack); 115 } 116 #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC 117 118 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 119 GET_CURRENT_PC_BP_SP; 120 (void)sp; 121 return asan_malloc_usable_size(ptr, pc, bp); 122 } 123 124 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 125 // We avoid including malloc.h for portability reasons. 126 // man mallinfo says the fields are "long", but the implementation uses int. 127 // It doesn't matter much -- we just need to make sure that the libc's mallinfo 128 // is not called. 129 struct fake_mallinfo { 130 int x[10]; 131 }; 132 133 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 134 struct fake_mallinfo res; 135 REAL(memset)(&res, 0, sizeof(res)); 136 return res; 137 } 138 139 INTERCEPTOR(int, mallopt, int cmd, int value) { 140 return 0; 141 } 142 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 143 144 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 145 GET_STACK_TRACE_MALLOC; 146 return asan_posix_memalign(memptr, alignment, size, &stack); 147 } 148 149 INTERCEPTOR(void*, valloc, uptr size) { 150 GET_STACK_TRACE_MALLOC; 151 return asan_valloc(size, &stack); 152 } 153 154 #if SANITIZER_INTERCEPT_PVALLOC 155 INTERCEPTOR(void*, pvalloc, uptr size) { 156 GET_STACK_TRACE_MALLOC; 157 return asan_pvalloc(size, &stack); 158 } 159 #endif // SANITIZER_INTERCEPT_PVALLOC 160 161 INTERCEPTOR(void, malloc_stats, void) { 162 __asan_print_accumulated_stats(); 163 } 164 165 #if SANITIZER_ANDROID 166 // Format of __libc_malloc_dispatch has changed in Android L. 167 // While we are moving towards a solution that does not depend on bionic 168 // internals, here is something to support both K* and L releases. 169 struct MallocDebugK { 170 void *(*malloc)(uptr bytes); 171 void (*free)(void *mem); 172 void *(*calloc)(uptr n_elements, uptr elem_size); 173 void *(*realloc)(void *oldMem, uptr bytes); 174 void *(*memalign)(uptr alignment, uptr bytes); 175 uptr (*malloc_usable_size)(void *mem); 176 }; 177 178 struct MallocDebugL { 179 void *(*calloc)(uptr n_elements, uptr elem_size); 180 void (*free)(void *mem); 181 fake_mallinfo (*mallinfo)(void); 182 void *(*malloc)(uptr bytes); 183 uptr (*malloc_usable_size)(void *mem); 184 void *(*memalign)(uptr alignment, uptr bytes); 185 int (*posix_memalign)(void **memptr, uptr alignment, uptr size); 186 void* (*pvalloc)(uptr size); 187 void *(*realloc)(void *oldMem, uptr bytes); 188 void* (*valloc)(uptr size); 189 }; 190 191 ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = { 192 WRAP(malloc), WRAP(free), WRAP(calloc), 193 WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; 194 195 ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = { 196 WRAP(calloc), WRAP(free), WRAP(mallinfo), 197 WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign), 198 WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc), 199 WRAP(valloc)}; 200 201 namespace __asan { 202 void ReplaceSystemMalloc() { 203 void **__libc_malloc_dispatch_p = 204 (void **)AsanDlSymNext("__libc_malloc_dispatch"); 205 if (__libc_malloc_dispatch_p) { 206 // Decide on K vs L dispatch format by the presence of 207 // __libc_malloc_default_dispatch export in libc. 208 void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch"); 209 if (default_dispatch_p) 210 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k; 211 else 212 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l; 213 } 214 } 215 } // namespace __asan 216 217 #else // SANITIZER_ANDROID 218 219 namespace __asan { 220 void ReplaceSystemMalloc() { 221 } 222 } // namespace __asan 223 #endif // SANITIZER_ANDROID 224 225 #endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || 226 // SANITIZER_NETBSD || SANITIZER_SOLARIS 227