1fe6060f1SDimitry Andric //===-- hwasan_allocation_functions.cpp -----------------------------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This file is a part of HWAddressSanitizer. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric // Definitions for __sanitizer allocation functions. 12fe6060f1SDimitry Andric // 13fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andric #include "hwasan.h" 16fe6060f1SDimitry Andric #include "interception/interception.h" 17349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_allocator_dlsym.h" 18fe6060f1SDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h" 1906c3fb27SDimitry Andric #include "sanitizer_common/sanitizer_mallinfo.h" 20fe6060f1SDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric using namespace __hwasan; 23fe6060f1SDimitry Andric 24349cc55cSDimitry Andric struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 25349cc55cSDimitry Andric static bool UseImpl() { return !hwasan_inited; } 2606c3fb27SDimitry Andric static void OnAllocate(const void *ptr, uptr size) { 2706c3fb27SDimitry Andric # if CAN_SANITIZE_LEAKS 2806c3fb27SDimitry Andric // Suppress leaks from dlerror(). Previously dlsym hack on global array was 2906c3fb27SDimitry Andric // used by leak sanitizer as a root region. 3006c3fb27SDimitry Andric __lsan_register_root_region(ptr, size); 3106c3fb27SDimitry Andric # endif 3206c3fb27SDimitry Andric } 3306c3fb27SDimitry Andric static void OnFree(const void *ptr, uptr size) { 3406c3fb27SDimitry Andric # if CAN_SANITIZE_LEAKS 3506c3fb27SDimitry Andric __lsan_unregister_root_region(ptr, size); 3606c3fb27SDimitry Andric # endif 3706c3fb27SDimitry Andric } 38349cc55cSDimitry Andric }; 39fe6060f1SDimitry Andric 40349cc55cSDimitry Andric extern "C" { 41fe6060f1SDimitry Andric 42349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 43fe6060f1SDimitry Andric int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) { 44fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 45fe6060f1SDimitry Andric CHECK_NE(memptr, 0); 46fe6060f1SDimitry Andric int res = hwasan_posix_memalign(memptr, alignment, size, &stack); 47fe6060f1SDimitry Andric return res; 48fe6060f1SDimitry Andric } 49fe6060f1SDimitry Andric 50349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 51fe6060f1SDimitry Andric void *__sanitizer_memalign(uptr alignment, uptr size) { 52fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 53fe6060f1SDimitry Andric return hwasan_memalign(alignment, size, &stack); 54fe6060f1SDimitry Andric } 55fe6060f1SDimitry Andric 56349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 57fe6060f1SDimitry Andric void *__sanitizer_aligned_alloc(uptr alignment, uptr size) { 58fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 59fe6060f1SDimitry Andric return hwasan_aligned_alloc(alignment, size, &stack); 60fe6060f1SDimitry Andric } 61fe6060f1SDimitry Andric 62349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 63fe6060f1SDimitry Andric void *__sanitizer___libc_memalign(uptr alignment, uptr size) { 64fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 65fe6060f1SDimitry Andric void *ptr = hwasan_memalign(alignment, size, &stack); 66fe6060f1SDimitry Andric if (ptr) 67fe6060f1SDimitry Andric DTLS_on_libc_memalign(ptr, size); 68fe6060f1SDimitry Andric return ptr; 69fe6060f1SDimitry Andric } 70fe6060f1SDimitry Andric 71349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 72fe6060f1SDimitry Andric void *__sanitizer_valloc(uptr size) { 73fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 74fe6060f1SDimitry Andric return hwasan_valloc(size, &stack); 75fe6060f1SDimitry Andric } 76fe6060f1SDimitry Andric 77349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 78fe6060f1SDimitry Andric void *__sanitizer_pvalloc(uptr size) { 79fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 80fe6060f1SDimitry Andric return hwasan_pvalloc(size, &stack); 81fe6060f1SDimitry Andric } 82fe6060f1SDimitry Andric 83349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 84fe6060f1SDimitry Andric void __sanitizer_free(void *ptr) { 85349cc55cSDimitry Andric if (!ptr) 86fe6060f1SDimitry Andric return; 87349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 88349cc55cSDimitry Andric return DlsymAlloc::Free(ptr); 89349cc55cSDimitry Andric GET_MALLOC_STACK_TRACE; 90fe6060f1SDimitry Andric hwasan_free(ptr, &stack); 91fe6060f1SDimitry Andric } 92fe6060f1SDimitry Andric 93349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 94fe6060f1SDimitry Andric void __sanitizer_cfree(void *ptr) { 95349cc55cSDimitry Andric if (!ptr) 96fe6060f1SDimitry Andric return; 97349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 98349cc55cSDimitry Andric return DlsymAlloc::Free(ptr); 99349cc55cSDimitry Andric GET_MALLOC_STACK_TRACE; 100fe6060f1SDimitry Andric hwasan_free(ptr, &stack); 101fe6060f1SDimitry Andric } 102fe6060f1SDimitry Andric 103349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 104fe6060f1SDimitry Andric uptr __sanitizer_malloc_usable_size(const void *ptr) { 105fe6060f1SDimitry Andric return __sanitizer_get_allocated_size(ptr); 106fe6060f1SDimitry Andric } 107fe6060f1SDimitry Andric 108349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 109fe6060f1SDimitry Andric struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() { 110fe6060f1SDimitry Andric __sanitizer_struct_mallinfo sret; 111fe6060f1SDimitry Andric internal_memset(&sret, 0, sizeof(sret)); 112fe6060f1SDimitry Andric return sret; 113fe6060f1SDimitry Andric } 114fe6060f1SDimitry Andric 115349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 116fe6060f1SDimitry Andric int __sanitizer_mallopt(int cmd, int value) { return 0; } 117fe6060f1SDimitry Andric 118349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 119fe6060f1SDimitry Andric void __sanitizer_malloc_stats(void) { 120fe6060f1SDimitry Andric // FIXME: implement, but don't call REAL(malloc_stats)! 121fe6060f1SDimitry Andric } 122fe6060f1SDimitry Andric 123349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 124fe6060f1SDimitry Andric void *__sanitizer_calloc(uptr nmemb, uptr size) { 125349cc55cSDimitry Andric if (DlsymAlloc::Use()) 126349cc55cSDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 127fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 128fe6060f1SDimitry Andric return hwasan_calloc(nmemb, size, &stack); 129fe6060f1SDimitry Andric } 130fe6060f1SDimitry Andric 131349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 132fe6060f1SDimitry Andric void *__sanitizer_realloc(void *ptr, uptr size) { 133349cc55cSDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 134349cc55cSDimitry Andric return DlsymAlloc::Realloc(ptr, size); 135fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 136fe6060f1SDimitry Andric return hwasan_realloc(ptr, size, &stack); 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric 139349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 140fe6060f1SDimitry Andric void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) { 141fe6060f1SDimitry Andric GET_MALLOC_STACK_TRACE; 142fe6060f1SDimitry Andric return hwasan_reallocarray(ptr, nmemb, size, &stack); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145349cc55cSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 146fe6060f1SDimitry Andric void *__sanitizer_malloc(uptr size) { 147fe6060f1SDimitry Andric if (UNLIKELY(!hwasan_init_is_running)) 148fe6060f1SDimitry Andric ENSURE_HWASAN_INITED(); 149349cc55cSDimitry Andric if (DlsymAlloc::Use()) 150349cc55cSDimitry Andric return DlsymAlloc::Allocate(size); 151349cc55cSDimitry Andric GET_MALLOC_STACK_TRACE; 152fe6060f1SDimitry Andric return hwasan_malloc(size, &stack); 153fe6060f1SDimitry Andric } 154fe6060f1SDimitry Andric 155349cc55cSDimitry Andric } // extern "C" 156349cc55cSDimitry Andric 15706c3fb27SDimitry Andric #if HWASAN_WITH_INTERCEPTORS || SANITIZER_FUCHSIA 15806c3fb27SDimitry Andric #if SANITIZER_FUCHSIA 15906c3fb27SDimitry Andric // Fuchsia does not use WRAP/wrappers used for the interceptor infrastructure. 16006c3fb27SDimitry Andric # define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ 16106c3fb27SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \ 16206c3fb27SDimitry Andric ARGS) ALIAS(__sanitizer_##FN) 16306c3fb27SDimitry Andric #else 164fe6060f1SDimitry Andric # define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ 165fe6060f1SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \ 16606c3fb27SDimitry Andric ALIAS(__sanitizer_##FN); \ 167fe6060f1SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \ 16806c3fb27SDimitry Andric ARGS) ALIAS(__sanitizer_##FN) 16906c3fb27SDimitry Andric #endif 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment, 172fe6060f1SDimitry Andric SIZE_T size); 173fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size); 174fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size); 175fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size); 176fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void, free, void *ptr); 177fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr); 178fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size); 179fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size); 180fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size); 181fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size); 182fe6060f1SDimitry Andric 183fe6060f1SDimitry Andric # if !SANITIZER_FREEBSD && !SANITIZER_NETBSD 184fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size); 185fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size); 186fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void, cfree, void *ptr); 187*0fca6ea1SDimitry Andric INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo,); 188fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value); 189fe6060f1SDimitry Andric INTERCEPTOR_ALIAS(void, malloc_stats, void); 190fe6060f1SDimitry Andric # endif 191fe6060f1SDimitry Andric #endif // #if HWASAN_WITH_INTERCEPTORS 192