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