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_interface.h"
18 #include "sanitizer_common/sanitizer_tls_get_addr.h"
19 
20 using namespace __hwasan;
21 
22 static uptr allocated_for_dlsym;
23 static const uptr kDlsymAllocPoolSize = 1024;
24 static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
25 
IsInDlsymAllocPool(const void * ptr)26 static bool IsInDlsymAllocPool(const void *ptr) {
27   uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
28   return off < sizeof(alloc_memory_for_dlsym);
29 }
30 
AllocateFromLocalPool(uptr size_in_bytes)31 static void *AllocateFromLocalPool(uptr size_in_bytes) {
32   uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize;
33   void *mem = (void *)&alloc_memory_for_dlsym[allocated_for_dlsym];
34   allocated_for_dlsym += size_in_words;
35   CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize);
36   return mem;
37 }
38 
__sanitizer_posix_memalign(void ** memptr,uptr alignment,uptr size)39 int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) {
40   GET_MALLOC_STACK_TRACE;
41   CHECK_NE(memptr, 0);
42   int res = hwasan_posix_memalign(memptr, alignment, size, &stack);
43   return res;
44 }
45 
__sanitizer_memalign(uptr alignment,uptr size)46 void *__sanitizer_memalign(uptr alignment, uptr size) {
47   GET_MALLOC_STACK_TRACE;
48   return hwasan_memalign(alignment, size, &stack);
49 }
50 
__sanitizer_aligned_alloc(uptr alignment,uptr size)51 void *__sanitizer_aligned_alloc(uptr alignment, uptr size) {
52   GET_MALLOC_STACK_TRACE;
53   return hwasan_aligned_alloc(alignment, size, &stack);
54 }
55 
__sanitizer___libc_memalign(uptr alignment,uptr size)56 void *__sanitizer___libc_memalign(uptr alignment, uptr size) {
57   GET_MALLOC_STACK_TRACE;
58   void *ptr = hwasan_memalign(alignment, size, &stack);
59   if (ptr)
60     DTLS_on_libc_memalign(ptr, size);
61   return ptr;
62 }
63 
__sanitizer_valloc(uptr size)64 void *__sanitizer_valloc(uptr size) {
65   GET_MALLOC_STACK_TRACE;
66   return hwasan_valloc(size, &stack);
67 }
68 
__sanitizer_pvalloc(uptr size)69 void *__sanitizer_pvalloc(uptr size) {
70   GET_MALLOC_STACK_TRACE;
71   return hwasan_pvalloc(size, &stack);
72 }
73 
__sanitizer_free(void * ptr)74 void __sanitizer_free(void *ptr) {
75   GET_MALLOC_STACK_TRACE;
76   if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr)))
77     return;
78   hwasan_free(ptr, &stack);
79 }
80 
__sanitizer_cfree(void * ptr)81 void __sanitizer_cfree(void *ptr) {
82   GET_MALLOC_STACK_TRACE;
83   if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr)))
84     return;
85   hwasan_free(ptr, &stack);
86 }
87 
__sanitizer_malloc_usable_size(const void * ptr)88 uptr __sanitizer_malloc_usable_size(const void *ptr) {
89   return __sanitizer_get_allocated_size(ptr);
90 }
91 
__sanitizer_mallinfo()92 struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() {
93   __sanitizer_struct_mallinfo sret;
94   internal_memset(&sret, 0, sizeof(sret));
95   return sret;
96 }
97 
__sanitizer_mallopt(int cmd,int value)98 int __sanitizer_mallopt(int cmd, int value) { return 0; }
99 
__sanitizer_malloc_stats(void)100 void __sanitizer_malloc_stats(void) {
101   // FIXME: implement, but don't call REAL(malloc_stats)!
102 }
103 
__sanitizer_calloc(uptr nmemb,uptr size)104 void *__sanitizer_calloc(uptr nmemb, uptr size) {
105   GET_MALLOC_STACK_TRACE;
106   if (UNLIKELY(!hwasan_inited))
107     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
108     return AllocateFromLocalPool(nmemb * size);
109   return hwasan_calloc(nmemb, size, &stack);
110 }
111 
__sanitizer_realloc(void * ptr,uptr size)112 void *__sanitizer_realloc(void *ptr, uptr size) {
113   GET_MALLOC_STACK_TRACE;
114   if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
115     uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
116     uptr copy_size = Min(size, kDlsymAllocPoolSize - offset);
117     void *new_ptr;
118     if (UNLIKELY(!hwasan_inited)) {
119       new_ptr = AllocateFromLocalPool(copy_size);
120     } else {
121       copy_size = size;
122       new_ptr = hwasan_malloc(copy_size, &stack);
123     }
124     internal_memcpy(new_ptr, ptr, copy_size);
125     return new_ptr;
126   }
127   return hwasan_realloc(ptr, size, &stack);
128 }
129 
__sanitizer_reallocarray(void * ptr,uptr nmemb,uptr size)130 void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
131   GET_MALLOC_STACK_TRACE;
132   return hwasan_reallocarray(ptr, nmemb, size, &stack);
133 }
134 
__sanitizer_malloc(uptr size)135 void *__sanitizer_malloc(uptr size) {
136   GET_MALLOC_STACK_TRACE;
137   if (UNLIKELY(!hwasan_init_is_running))
138     ENSURE_HWASAN_INITED();
139   if (UNLIKELY(!hwasan_inited))
140     // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym.
141     return AllocateFromLocalPool(size);
142   return hwasan_malloc(size, &stack);
143 }
144 
145 #if HWASAN_WITH_INTERCEPTORS
146 #  define INTERCEPTOR_ALIAS(RET, FN, ARGS...)                                 \
147     extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS)               \
148         ALIAS("__sanitizer_" #FN);                                            \
149     extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \
150         ARGS) ALIAS("__sanitizer_" #FN)
151 
152 INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment,
153                   SIZE_T size);
154 INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size);
155 INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size);
156 INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size);
157 INTERCEPTOR_ALIAS(void, free, void *ptr);
158 INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
159 INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
160 INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);
161 INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size);
162 INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size);
163 
164 #  if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
165 INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size);
166 INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size);
167 INTERCEPTOR_ALIAS(void, cfree, void *ptr);
168 INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo);
169 INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
170 INTERCEPTOR_ALIAS(void, malloc_stats, void);
171 #  endif
172 #endif  // #if HWASAN_WITH_INTERCEPTORS
173