Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp
35234 views
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
alignas(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
alignas(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
225