xref: /freebsd/contrib/llvm-project/compiler-rt/lib/nsan/nsan_malloc_linux.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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> {
UseImpl__anon0d1da7f80111::DlsymAlloc26*0fca6ea1SDimitry Andric   static bool UseImpl() { return !nsan_initialized; }
27*0fca6ea1SDimitry Andric };
28*0fca6ea1SDimitry Andric } // namespace
29*0fca6ea1SDimitry Andric 
INTERCEPTOR(void *,aligned_alloc,uptr align,uptr size)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 
INTERCEPTOR(void *,calloc,uptr nmemb,uptr size)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 
INTERCEPTOR(void,free,void * ptr)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 
INTERCEPTOR(void *,malloc,uptr size)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 
INTERCEPTOR(void *,realloc,void * ptr,uptr size)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
INTERCEPTOR(void *,reallocarray,void * ptr,uptr nmemb,uptr size)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 
INTERCEPTOR(int,posix_memalign,void ** memptr,uptr align,uptr size)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
INTERCEPTOR(void *,memalign,uptr align,uptr size)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 
INTERCEPTOR(void *,__libc_memalign,uptr align,uptr size)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 
InitializeMallocInterceptors()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