1*0fca6ea1SDimitry Andric //===- nsan_malloc_linux.cpp ----------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // Interceptors for memory allocation functions on ELF OSes. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "interception/interception.h" 14*0fca6ea1SDimitry Andric #include "nsan/nsan.h" 15*0fca6ea1SDimitry Andric #include "sanitizer_common/sanitizer_allocator_dlsym.h" 16*0fca6ea1SDimitry Andric #include "sanitizer_common/sanitizer_common.h" 17*0fca6ea1SDimitry Andric #include "sanitizer_common/sanitizer_platform.h" 18*0fca6ea1SDimitry Andric #include "sanitizer_common/sanitizer_platform_interceptors.h" 19*0fca6ea1SDimitry Andric 20*0fca6ea1SDimitry Andric #if !SANITIZER_APPLE && !SANITIZER_WINDOWS 21*0fca6ea1SDimitry Andric using namespace __sanitizer; 22*0fca6ea1SDimitry Andric using __nsan::nsan_initialized; 23*0fca6ea1SDimitry Andric 24*0fca6ea1SDimitry Andric namespace { 25*0fca6ea1SDimitry Andric struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 26*0fca6ea1SDimitry Andric static bool UseImpl() { return !nsan_initialized; } 27*0fca6ea1SDimitry Andric }; 28*0fca6ea1SDimitry Andric } // namespace 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric INTERCEPTOR(void *, aligned_alloc, uptr align, uptr size) { 31*0fca6ea1SDimitry Andric void *res = REAL(aligned_alloc)(align, size); 32*0fca6ea1SDimitry Andric if (res) 33*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), size); 34*0fca6ea1SDimitry Andric return res; 35*0fca6ea1SDimitry Andric } 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) { 38*0fca6ea1SDimitry Andric if (DlsymAlloc::Use()) 39*0fca6ea1SDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric void *res = REAL(calloc)(nmemb, size); 42*0fca6ea1SDimitry Andric if (res) 43*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), nmemb * size); 44*0fca6ea1SDimitry Andric return res; 45*0fca6ea1SDimitry Andric } 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric INTERCEPTOR(void, free, void *ptr) { 48*0fca6ea1SDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 49*0fca6ea1SDimitry Andric return DlsymAlloc::Free(ptr); 50*0fca6ea1SDimitry Andric REAL(free)(ptr); 51*0fca6ea1SDimitry Andric } 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric INTERCEPTOR(void *, malloc, uptr size) { 54*0fca6ea1SDimitry Andric if (DlsymAlloc::Use()) 55*0fca6ea1SDimitry Andric return DlsymAlloc::Allocate(size); 56*0fca6ea1SDimitry Andric void *res = REAL(malloc)(size); 57*0fca6ea1SDimitry Andric if (res) 58*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), size); 59*0fca6ea1SDimitry Andric return res; 60*0fca6ea1SDimitry Andric } 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric INTERCEPTOR(void *, realloc, void *ptr, uptr size) { 63*0fca6ea1SDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 64*0fca6ea1SDimitry Andric return DlsymAlloc::Realloc(ptr, size); 65*0fca6ea1SDimitry Andric void *res = REAL(realloc)(ptr, size); 66*0fca6ea1SDimitry Andric // TODO: We might want to copy the types from the original allocation 67*0fca6ea1SDimitry Andric // (although that would require that we know its size). 68*0fca6ea1SDimitry Andric if (res) 69*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), size); 70*0fca6ea1SDimitry Andric return res; 71*0fca6ea1SDimitry Andric } 72*0fca6ea1SDimitry Andric 73*0fca6ea1SDimitry Andric #if SANITIZER_INTERCEPT_REALLOCARRAY 74*0fca6ea1SDimitry Andric INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) { 75*0fca6ea1SDimitry Andric void *res = REAL(reallocarray)(ptr, nmemb, size); 76*0fca6ea1SDimitry Andric if (res) 77*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), nmemb * size); 78*0fca6ea1SDimitry Andric return res; 79*0fca6ea1SDimitry Andric } 80*0fca6ea1SDimitry Andric #endif // SANITIZER_INTERCEPT_REALLOCARRAY 81*0fca6ea1SDimitry Andric 82*0fca6ea1SDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr size) { 83*0fca6ea1SDimitry Andric int res = REAL(posix_memalign)(memptr, align, size); 84*0fca6ea1SDimitry Andric if (res == 0 && *memptr) 85*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(*memptr), size); 86*0fca6ea1SDimitry Andric return res; 87*0fca6ea1SDimitry Andric } 88*0fca6ea1SDimitry Andric 89*0fca6ea1SDimitry Andric // Deprecated allocation functions (memalign, etc). 90*0fca6ea1SDimitry Andric #if SANITIZER_INTERCEPT_MEMALIGN 91*0fca6ea1SDimitry Andric INTERCEPTOR(void *, memalign, uptr align, uptr size) { 92*0fca6ea1SDimitry Andric void *const res = REAL(memalign)(align, size); 93*0fca6ea1SDimitry Andric if (res) 94*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), size); 95*0fca6ea1SDimitry Andric return res; 96*0fca6ea1SDimitry Andric } 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric INTERCEPTOR(void *, __libc_memalign, uptr align, uptr size) { 99*0fca6ea1SDimitry Andric void *const res = REAL(__libc_memalign)(align, size); 100*0fca6ea1SDimitry Andric if (res) 101*0fca6ea1SDimitry Andric __nsan_set_value_unknown(static_cast<u8 *>(res), size); 102*0fca6ea1SDimitry Andric return res; 103*0fca6ea1SDimitry Andric } 104*0fca6ea1SDimitry Andric #endif 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric void __nsan::InitializeMallocInterceptors() { 107*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(aligned_alloc); 108*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(calloc); 109*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(free); 110*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(malloc); 111*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(posix_memalign); 112*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(realloc); 113*0fca6ea1SDimitry Andric #if SANITIZER_INTERCEPT_REALLOCARRAY 114*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(reallocarray); 115*0fca6ea1SDimitry Andric #endif 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric #if SANITIZER_INTERCEPT_MEMALIGN 118*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(memalign); 119*0fca6ea1SDimitry Andric INTERCEPT_FUNCTION(__libc_memalign); 120*0fca6ea1SDimitry Andric #endif 121*0fca6ea1SDimitry Andric } 122*0fca6ea1SDimitry Andric 123*0fca6ea1SDimitry Andric #endif 124