1217222abSNico Weber //===-- asan_malloc_linux.cpp ---------------------------------------------===//
2217222abSNico Weber //
3217222abSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4217222abSNico Weber // See https://llvm.org/LICENSE.txt for license information.
5217222abSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6217222abSNico Weber //
7217222abSNico Weber //===----------------------------------------------------------------------===//
8217222abSNico Weber //
9217222abSNico Weber // This file is a part of AddressSanitizer, an address sanity checker.
10217222abSNico Weber //
11217222abSNico Weber // Linux-specific malloc interception.
12217222abSNico Weber // We simply define functions like malloc, free, realloc, etc.
13217222abSNico Weber // They will replace the corresponding libc functions automagically.
14217222abSNico Weber //===----------------------------------------------------------------------===//
15217222abSNico Weber
16217222abSNico Weber #include "sanitizer_common/sanitizer_platform.h"
17217222abSNico Weber #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \
186478ef61SVitaly Buka SANITIZER_NETBSD || SANITIZER_SOLARIS
19217222abSNico Weber
20217222abSNico Weber # include "asan_allocator.h"
21217222abSNico Weber # include "asan_interceptors.h"
22217222abSNico Weber # include "asan_internal.h"
23217222abSNico Weber # include "asan_stack.h"
24*cb0e14ceSVitaly Buka # include "lsan/lsan_common.h"
25b8919fb0SVitaly Buka # include "sanitizer_common/sanitizer_allocator_checks.h"
26*cb0e14ceSVitaly Buka # include "sanitizer_common/sanitizer_allocator_dlsym.h"
27b8919fb0SVitaly Buka # include "sanitizer_common/sanitizer_errno.h"
28b8919fb0SVitaly Buka # include "sanitizer_common/sanitizer_tls_get_addr.h"
29217222abSNico Weber
30217222abSNico Weber // ---------------------- Replacement functions ---------------- {{{1
31c0fa6322SVitaly Buka using namespace __asan;
32217222abSNico Weber
33*cb0e14ceSVitaly Buka struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc34*cb0e14ceSVitaly Buka static bool UseImpl() { return asan_init_is_running; }
OnAllocateDlsymAlloc35*cb0e14ceSVitaly Buka static void OnAllocate(const void *ptr, uptr size) {
36*cb0e14ceSVitaly Buka # if CAN_SANITIZE_LEAKS
37*cb0e14ceSVitaly Buka // Suppress leaks from dlerror(). Previously dlsym hack on global array was
38*cb0e14ceSVitaly Buka // used by leak sanitizer as a root region.
39*cb0e14ceSVitaly Buka __lsan_register_root_region(ptr, size);
40*cb0e14ceSVitaly Buka # endif
41217222abSNico Weber }
OnFreeDlsymAlloc42*cb0e14ceSVitaly Buka static void OnFree(const void *ptr, uptr size) {
43*cb0e14ceSVitaly Buka # if CAN_SANITIZE_LEAKS
44*cb0e14ceSVitaly Buka __lsan_unregister_root_region(ptr, size);
45*cb0e14ceSVitaly Buka # endif
46217222abSNico Weber }
47*cb0e14ceSVitaly Buka };
48217222abSNico Weber
INTERCEPTOR(void,free,void * ptr)49217222abSNico Weber INTERCEPTOR(void, free, void *ptr) {
50*cb0e14ceSVitaly Buka if (DlsymAlloc::PointerIsMine(ptr))
51*cb0e14ceSVitaly Buka return DlsymAlloc::Free(ptr);
526cf72ad3SVitaly Buka GET_STACK_TRACE_FREE;
53217222abSNico Weber asan_free(ptr, &stack, FROM_MALLOC);
54217222abSNico Weber }
55217222abSNico Weber
56217222abSNico Weber #if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void,cfree,void * ptr)57217222abSNico Weber INTERCEPTOR(void, cfree, void *ptr) {
58*cb0e14ceSVitaly Buka if (DlsymAlloc::PointerIsMine(ptr))
59*cb0e14ceSVitaly Buka return DlsymAlloc::Free(ptr);
606cf72ad3SVitaly Buka GET_STACK_TRACE_FREE;
61217222abSNico Weber asan_free(ptr, &stack, FROM_MALLOC);
62217222abSNico Weber }
63217222abSNico Weber #endif // SANITIZER_INTERCEPT_CFREE
64217222abSNico Weber
INTERCEPTOR(void *,malloc,uptr size)65217222abSNico Weber INTERCEPTOR(void*, malloc, uptr size) {
66*cb0e14ceSVitaly Buka if (DlsymAlloc::Use())
67*cb0e14ceSVitaly Buka return DlsymAlloc::Allocate(size);
68217222abSNico Weber ENSURE_ASAN_INITED();
69217222abSNico Weber GET_STACK_TRACE_MALLOC;
70217222abSNico Weber return asan_malloc(size, &stack);
71217222abSNico Weber }
72217222abSNico Weber
INTERCEPTOR(void *,calloc,uptr nmemb,uptr size)73217222abSNico Weber INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
74*cb0e14ceSVitaly Buka if (DlsymAlloc::Use())
75*cb0e14ceSVitaly Buka return DlsymAlloc::Callocate(nmemb, size);
76217222abSNico Weber ENSURE_ASAN_INITED();
77217222abSNico Weber GET_STACK_TRACE_MALLOC;
78217222abSNico Weber return asan_calloc(nmemb, size, &stack);
79217222abSNico Weber }
80217222abSNico Weber
INTERCEPTOR(void *,realloc,void * ptr,uptr size)81217222abSNico Weber INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
82*cb0e14ceSVitaly Buka if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
83*cb0e14ceSVitaly Buka return DlsymAlloc::Realloc(ptr, size);
84217222abSNico Weber ENSURE_ASAN_INITED();
85217222abSNico Weber GET_STACK_TRACE_MALLOC;
86217222abSNico Weber return asan_realloc(ptr, size, &stack);
87217222abSNico Weber }
88217222abSNico Weber
89217222abSNico Weber #if SANITIZER_INTERCEPT_REALLOCARRAY
INTERCEPTOR(void *,reallocarray,void * ptr,uptr nmemb,uptr size)90217222abSNico Weber INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {
91217222abSNico Weber ENSURE_ASAN_INITED();
92217222abSNico Weber GET_STACK_TRACE_MALLOC;
93217222abSNico Weber return asan_reallocarray(ptr, nmemb, size, &stack);
94217222abSNico Weber }
95217222abSNico Weber #endif // SANITIZER_INTERCEPT_REALLOCARRAY
96217222abSNico Weber
97217222abSNico Weber #if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void *,memalign,uptr boundary,uptr size)98217222abSNico Weber INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
99217222abSNico Weber GET_STACK_TRACE_MALLOC;
100217222abSNico Weber return asan_memalign(boundary, size, &stack, FROM_MALLOC);
101217222abSNico Weber }
102217222abSNico Weber
INTERCEPTOR(void *,__libc_memalign,uptr boundary,uptr size)103217222abSNico Weber INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
104217222abSNico Weber GET_STACK_TRACE_MALLOC;
105217222abSNico Weber void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
106217222abSNico Weber DTLS_on_libc_memalign(res, size);
107217222abSNico Weber return res;
108217222abSNico Weber }
109217222abSNico Weber #endif // SANITIZER_INTERCEPT_MEMALIGN
110217222abSNico Weber
111217222abSNico Weber #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
INTERCEPTOR(void *,aligned_alloc,uptr boundary,uptr size)112217222abSNico Weber INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
113217222abSNico Weber GET_STACK_TRACE_MALLOC;
114217222abSNico Weber return asan_aligned_alloc(boundary, size, &stack);
115217222abSNico Weber }
116217222abSNico Weber #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
117217222abSNico Weber
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)118217222abSNico Weber INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
119217222abSNico Weber GET_CURRENT_PC_BP_SP;
120217222abSNico Weber (void)sp;
121217222abSNico Weber return asan_malloc_usable_size(ptr, pc, bp);
122217222abSNico Weber }
123217222abSNico Weber
124217222abSNico Weber #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
125217222abSNico Weber // We avoid including malloc.h for portability reasons.
126217222abSNico Weber // man mallinfo says the fields are "long", but the implementation uses int.
127217222abSNico Weber // It doesn't matter much -- we just need to make sure that the libc's mallinfo
128217222abSNico Weber // is not called.
129217222abSNico Weber struct fake_mallinfo {
130217222abSNico Weber int x[10];
131217222abSNico Weber };
132217222abSNico Weber
INTERCEPTOR(struct fake_mallinfo,mallinfo,void)133217222abSNico Weber INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
134217222abSNico Weber struct fake_mallinfo res;
135217222abSNico Weber REAL(memset)(&res, 0, sizeof(res));
136217222abSNico Weber return res;
137217222abSNico Weber }
138217222abSNico Weber
INTERCEPTOR(int,mallopt,int cmd,int value)139217222abSNico Weber INTERCEPTOR(int, mallopt, int cmd, int value) {
140217222abSNico Weber return 0;
141217222abSNico Weber }
142217222abSNico Weber #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
143217222abSNico Weber
INTERCEPTOR(int,posix_memalign,void ** memptr,uptr alignment,uptr size)144217222abSNico Weber INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
145217222abSNico Weber GET_STACK_TRACE_MALLOC;
146217222abSNico Weber return asan_posix_memalign(memptr, alignment, size, &stack);
147217222abSNico Weber }
148217222abSNico Weber
INTERCEPTOR(void *,valloc,uptr size)149217222abSNico Weber INTERCEPTOR(void*, valloc, uptr size) {
150217222abSNico Weber GET_STACK_TRACE_MALLOC;
151217222abSNico Weber return asan_valloc(size, &stack);
152217222abSNico Weber }
153217222abSNico Weber
154217222abSNico Weber #if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void *,pvalloc,uptr size)155217222abSNico Weber INTERCEPTOR(void*, pvalloc, uptr size) {
156217222abSNico Weber GET_STACK_TRACE_MALLOC;
157217222abSNico Weber return asan_pvalloc(size, &stack);
158217222abSNico Weber }
159217222abSNico Weber #endif // SANITIZER_INTERCEPT_PVALLOC
160217222abSNico Weber
INTERCEPTOR(void,malloc_stats,void)161217222abSNico Weber INTERCEPTOR(void, malloc_stats, void) {
162217222abSNico Weber __asan_print_accumulated_stats();
163217222abSNico Weber }
164217222abSNico Weber
165217222abSNico Weber #if SANITIZER_ANDROID
166217222abSNico Weber // Format of __libc_malloc_dispatch has changed in Android L.
167217222abSNico Weber // While we are moving towards a solution that does not depend on bionic
168217222abSNico Weber // internals, here is something to support both K* and L releases.
169217222abSNico Weber struct MallocDebugK {
170217222abSNico Weber void *(*malloc)(uptr bytes);
171217222abSNico Weber void (*free)(void *mem);
172217222abSNico Weber void *(*calloc)(uptr n_elements, uptr elem_size);
173217222abSNico Weber void *(*realloc)(void *oldMem, uptr bytes);
174217222abSNico Weber void *(*memalign)(uptr alignment, uptr bytes);
175217222abSNico Weber uptr (*malloc_usable_size)(void *mem);
176217222abSNico Weber };
177217222abSNico Weber
178217222abSNico Weber struct MallocDebugL {
179217222abSNico Weber void *(*calloc)(uptr n_elements, uptr elem_size);
180217222abSNico Weber void (*free)(void *mem);
181217222abSNico Weber fake_mallinfo (*mallinfo)(void);
182217222abSNico Weber void *(*malloc)(uptr bytes);
183217222abSNico Weber uptr (*malloc_usable_size)(void *mem);
184217222abSNico Weber void *(*memalign)(uptr alignment, uptr bytes);
185217222abSNico Weber int (*posix_memalign)(void **memptr, uptr alignment, uptr size);
186217222abSNico Weber void* (*pvalloc)(uptr size);
187217222abSNico Weber void *(*realloc)(void *oldMem, uptr bytes);
188217222abSNico Weber void* (*valloc)(uptr size);
189217222abSNico Weber };
190217222abSNico Weber
191217222abSNico Weber ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = {
192217222abSNico Weber WRAP(malloc), WRAP(free), WRAP(calloc),
193217222abSNico Weber WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};
194217222abSNico Weber
195217222abSNico Weber ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = {
196217222abSNico Weber WRAP(calloc), WRAP(free), WRAP(mallinfo),
197217222abSNico Weber WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign),
198217222abSNico Weber WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc),
199217222abSNico Weber WRAP(valloc)};
200217222abSNico Weber
201217222abSNico Weber namespace __asan {
ReplaceSystemMalloc()202217222abSNico Weber void ReplaceSystemMalloc() {
203217222abSNico Weber void **__libc_malloc_dispatch_p =
204217222abSNico Weber (void **)AsanDlSymNext("__libc_malloc_dispatch");
205217222abSNico Weber if (__libc_malloc_dispatch_p) {
206217222abSNico Weber // Decide on K vs L dispatch format by the presence of
207217222abSNico Weber // __libc_malloc_default_dispatch export in libc.
208217222abSNico Weber void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");
209217222abSNico Weber if (default_dispatch_p)
210217222abSNico Weber *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;
211217222abSNico Weber else
212217222abSNico Weber *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;
213217222abSNico Weber }
214217222abSNico Weber }
215217222abSNico Weber } // namespace __asan
216217222abSNico Weber
217217222abSNico Weber #else // SANITIZER_ANDROID
218217222abSNico Weber
219217222abSNico Weber namespace __asan {
ReplaceSystemMalloc()220217222abSNico Weber void ReplaceSystemMalloc() {
221217222abSNico Weber }
222217222abSNico Weber } // namespace __asan
223217222abSNico Weber #endif // SANITIZER_ANDROID
224217222abSNico Weber
225217222abSNico Weber #endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX ||
226217222abSNico Weber // SANITIZER_NETBSD || SANITIZER_SOLARIS
227