1 | //===-- hwasan_allocation_functions.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 HWAddressSanitizer. |
10 | // |
11 | // Definitions for __sanitizer allocation functions. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "hwasan.h" |
16 | #include "interception/interception.h" |
17 | #include "sanitizer_common/sanitizer_allocator_dlsym.h" |
18 | #include "sanitizer_common/sanitizer_allocator_interface.h" |
19 | #include "sanitizer_common/sanitizer_mallinfo.h" |
20 | #include "sanitizer_common/sanitizer_tls_get_addr.h" |
21 | |
22 | using namespace __hwasan; |
23 | |
24 | struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { |
25 | static bool UseImpl() { return !hwasan_inited; } |
26 | static void OnAllocate(const void *ptr, uptr size) { |
27 | # if CAN_SANITIZE_LEAKS |
28 | // Suppress leaks from dlerror(). Previously dlsym hack on global array was |
29 | // used by leak sanitizer as a root region. |
30 | __lsan_register_root_region(ptr, size); |
31 | # endif |
32 | } |
33 | static void OnFree(const void *ptr, uptr size) { |
34 | # if CAN_SANITIZE_LEAKS |
35 | __lsan_unregister_root_region(ptr, size); |
36 | # endif |
37 | } |
38 | }; |
39 | |
40 | extern "C" { |
41 | |
42 | SANITIZER_INTERFACE_ATTRIBUTE |
43 | int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) { |
44 | GET_MALLOC_STACK_TRACE; |
45 | CHECK_NE(memptr, 0); |
46 | int res = hwasan_posix_memalign(memptr, alignment, size, stack: &stack); |
47 | return res; |
48 | } |
49 | |
50 | SANITIZER_INTERFACE_ATTRIBUTE |
51 | void *__sanitizer_memalign(uptr alignment, uptr size) { |
52 | GET_MALLOC_STACK_TRACE; |
53 | return hwasan_memalign(alignment, size, stack: &stack); |
54 | } |
55 | |
56 | SANITIZER_INTERFACE_ATTRIBUTE |
57 | void *__sanitizer_aligned_alloc(uptr alignment, uptr size) { |
58 | GET_MALLOC_STACK_TRACE; |
59 | return hwasan_aligned_alloc(alignment, size, stack: &stack); |
60 | } |
61 | |
62 | SANITIZER_INTERFACE_ATTRIBUTE |
63 | void *__sanitizer___libc_memalign(uptr alignment, uptr size) { |
64 | GET_MALLOC_STACK_TRACE; |
65 | void *ptr = hwasan_memalign(alignment, size, stack: &stack); |
66 | if (ptr) |
67 | DTLS_on_libc_memalign(ptr, size); |
68 | return ptr; |
69 | } |
70 | |
71 | SANITIZER_INTERFACE_ATTRIBUTE |
72 | void *__sanitizer_valloc(uptr size) { |
73 | GET_MALLOC_STACK_TRACE; |
74 | return hwasan_valloc(size, stack: &stack); |
75 | } |
76 | |
77 | SANITIZER_INTERFACE_ATTRIBUTE |
78 | void *__sanitizer_pvalloc(uptr size) { |
79 | GET_MALLOC_STACK_TRACE; |
80 | return hwasan_pvalloc(size, stack: &stack); |
81 | } |
82 | |
83 | SANITIZER_INTERFACE_ATTRIBUTE |
84 | void __sanitizer_free(void *ptr) { |
85 | if (!ptr) |
86 | return; |
87 | if (DlsymAlloc::PointerIsMine(ptr)) |
88 | return DlsymAlloc::Free(ptr); |
89 | GET_MALLOC_STACK_TRACE; |
90 | hwasan_free(ptr, stack: &stack); |
91 | } |
92 | |
93 | SANITIZER_INTERFACE_ATTRIBUTE |
94 | void __sanitizer_cfree(void *ptr) { |
95 | if (!ptr) |
96 | return; |
97 | if (DlsymAlloc::PointerIsMine(ptr)) |
98 | return DlsymAlloc::Free(ptr); |
99 | GET_MALLOC_STACK_TRACE; |
100 | hwasan_free(ptr, stack: &stack); |
101 | } |
102 | |
103 | SANITIZER_INTERFACE_ATTRIBUTE |
104 | uptr __sanitizer_malloc_usable_size(const void *ptr) { |
105 | return __sanitizer_get_allocated_size(p: ptr); |
106 | } |
107 | |
108 | SANITIZER_INTERFACE_ATTRIBUTE |
109 | struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() { |
110 | __sanitizer_struct_mallinfo sret; |
111 | internal_memset(s: &sret, c: 0, n: sizeof(sret)); |
112 | return sret; |
113 | } |
114 | |
115 | SANITIZER_INTERFACE_ATTRIBUTE |
116 | int __sanitizer_mallopt(int cmd, int value) { return 0; } |
117 | |
118 | SANITIZER_INTERFACE_ATTRIBUTE |
119 | void __sanitizer_malloc_stats(void) { |
120 | // FIXME: implement, but don't call REAL(malloc_stats)! |
121 | } |
122 | |
123 | SANITIZER_INTERFACE_ATTRIBUTE |
124 | void *__sanitizer_calloc(uptr nmemb, uptr size) { |
125 | if (DlsymAlloc::Use()) |
126 | return DlsymAlloc::Callocate(nmemb, size); |
127 | GET_MALLOC_STACK_TRACE; |
128 | return hwasan_calloc(nmemb, size, stack: &stack); |
129 | } |
130 | |
131 | SANITIZER_INTERFACE_ATTRIBUTE |
132 | void *__sanitizer_realloc(void *ptr, uptr size) { |
133 | if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) |
134 | return DlsymAlloc::Realloc(ptr, new_size: size); |
135 | GET_MALLOC_STACK_TRACE; |
136 | return hwasan_realloc(ptr, size, stack: &stack); |
137 | } |
138 | |
139 | SANITIZER_INTERFACE_ATTRIBUTE |
140 | void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) { |
141 | GET_MALLOC_STACK_TRACE; |
142 | return hwasan_reallocarray(ptr, nmemb, size, stack: &stack); |
143 | } |
144 | |
145 | SANITIZER_INTERFACE_ATTRIBUTE |
146 | void *__sanitizer_malloc(uptr size) { |
147 | if (UNLIKELY(!hwasan_init_is_running)) |
148 | ENSURE_HWASAN_INITED(); |
149 | if (DlsymAlloc::Use()) |
150 | return DlsymAlloc::Allocate(size_in_bytes: size); |
151 | GET_MALLOC_STACK_TRACE; |
152 | return hwasan_malloc(size, stack: &stack); |
153 | } |
154 | |
155 | } // extern "C" |
156 | |
157 | #if HWASAN_WITH_INTERCEPTORS || SANITIZER_FUCHSIA |
158 | #if SANITIZER_FUCHSIA |
159 | // Fuchsia does not use WRAP/wrappers used for the interceptor infrastructure. |
160 | # define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ |
161 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \ |
162 | ARGS) ALIAS(__sanitizer_##FN) |
163 | #else |
164 | # define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ |
165 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \ |
166 | ALIAS(__sanitizer_##FN); \ |
167 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \ |
168 | ARGS) ALIAS(__sanitizer_##FN) |
169 | #endif |
170 | |
171 | INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment, |
172 | SIZE_T size); |
173 | INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size); |
174 | INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size); |
175 | INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size); |
176 | INTERCEPTOR_ALIAS(void, free, void *ptr); |
177 | INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr); |
178 | INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size); |
179 | INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size); |
180 | INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size); |
181 | INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size); |
182 | |
183 | # if !SANITIZER_FREEBSD && !SANITIZER_NETBSD |
184 | INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size); |
185 | INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size); |
186 | INTERCEPTOR_ALIAS(void, cfree, void *ptr); |
187 | INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo,); |
188 | INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value); |
189 | INTERCEPTOR_ALIAS(void, malloc_stats, void); |
190 | # endif |
191 | #endif // #if HWASAN_WITH_INTERCEPTORS |
192 | |