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 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 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 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 46 void *__sanitizer_memalign(uptr alignment, uptr size) { 47 GET_MALLOC_STACK_TRACE; 48 return hwasan_memalign(alignment, size, &stack); 49 } 50 51 void *__sanitizer_aligned_alloc(uptr alignment, uptr size) { 52 GET_MALLOC_STACK_TRACE; 53 return hwasan_aligned_alloc(alignment, size, &stack); 54 } 55 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 64 void *__sanitizer_valloc(uptr size) { 65 GET_MALLOC_STACK_TRACE; 66 return hwasan_valloc(size, &stack); 67 } 68 69 void *__sanitizer_pvalloc(uptr size) { 70 GET_MALLOC_STACK_TRACE; 71 return hwasan_pvalloc(size, &stack); 72 } 73 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 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 88 uptr __sanitizer_malloc_usable_size(const void *ptr) { 89 return __sanitizer_get_allocated_size(ptr); 90 } 91 92 struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() { 93 __sanitizer_struct_mallinfo sret; 94 internal_memset(&sret, 0, sizeof(sret)); 95 return sret; 96 } 97 98 int __sanitizer_mallopt(int cmd, int value) { return 0; } 99 100 void __sanitizer_malloc_stats(void) { 101 // FIXME: implement, but don't call REAL(malloc_stats)! 102 } 103 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 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 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 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