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