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(addr: 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(addr: static_cast<u8 *>(res), size: 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_in_bytes: size); |
56 | void *res = REAL(malloc)(size); |
57 | if (res) |
58 | __nsan_set_value_unknown(addr: 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, new_size: 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(addr: 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(addr: static_cast<u8 *>(res), size: 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(addr: 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(addr: 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(addr: 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 | |