1 //===-- dfsan_interceptors.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of DataFlowSanitizer.
11 // Interceptors for standard library functions.
12 //===----------------------------------------------------------------------===//
14 #include <sys/syscall.h>
17 #include "dfsan/dfsan.h"
18 #include "dfsan/dfsan_thread.h"
19 #include "interception/interception.h"
20 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
21 #include "sanitizer_common/sanitizer_allocator_interface.h"
22 #include "sanitizer_common/sanitizer_common.h"
23 #include "sanitizer_common/sanitizer_errno.h"
24 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
25 #include "sanitizer_common/sanitizer_posix.h"
26 #include "sanitizer_common/sanitizer_tls_get_addr.h"
28 using namespace __sanitizer
;
30 static bool interceptors_initialized
;
32 struct DlsymAlloc
: public DlSymAllocator
<DlsymAlloc
> {
33 static bool UseImpl() { return !__dfsan::dfsan_inited
; }
36 INTERCEPTOR(void *, reallocarray
, void *ptr
, SIZE_T nmemb
, SIZE_T size
) {
37 return __dfsan::dfsan_reallocarray(ptr
, nmemb
, size
);
40 INTERCEPTOR(void *, __libc_memalign
, SIZE_T alignment
, SIZE_T size
) {
41 void *ptr
= __dfsan::dfsan_memalign(alignment
, size
);
43 DTLS_on_libc_memalign(ptr
, size
);
47 INTERCEPTOR(void *, aligned_alloc
, SIZE_T alignment
, SIZE_T size
) {
48 return __dfsan::dfsan_aligned_alloc(alignment
, size
);
51 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
52 if (DlsymAlloc::Use())
53 return DlsymAlloc::Callocate(nmemb
, size
);
54 return __dfsan::dfsan_calloc(nmemb
, size
);
57 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
58 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr
))
59 return DlsymAlloc::Realloc(ptr
, size
);
60 return __dfsan::dfsan_realloc(ptr
, size
);
63 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
64 if (DlsymAlloc::Use())
65 return DlsymAlloc::Allocate(size
);
66 return __dfsan::dfsan_malloc(size
);
69 INTERCEPTOR(void, free
, void *ptr
) {
72 if (DlsymAlloc::PointerIsMine(ptr
))
73 return DlsymAlloc::Free(ptr
);
74 return __dfsan::dfsan_deallocate(ptr
);
77 INTERCEPTOR(void, cfree
, void *ptr
) {
80 if (DlsymAlloc::PointerIsMine(ptr
))
81 return DlsymAlloc::Free(ptr
);
82 return __dfsan::dfsan_deallocate(ptr
);
85 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
87 int res
= __dfsan::dfsan_posix_memalign(memptr
, alignment
, size
);
89 dfsan_set_label(0, memptr
, sizeof(*memptr
));
93 INTERCEPTOR(void *, memalign
, SIZE_T alignment
, SIZE_T size
) {
94 return __dfsan::dfsan_memalign(alignment
, size
);
97 INTERCEPTOR(void *, valloc
, SIZE_T size
) { return __dfsan::dfsan_valloc(size
); }
99 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
100 return __dfsan::dfsan_pvalloc(size
);
103 INTERCEPTOR(void, mallinfo
, __sanitizer_struct_mallinfo
*sret
) {
104 internal_memset(sret
, 0, sizeof(*sret
));
105 dfsan_set_label(0, sret
, sizeof(*sret
));
108 INTERCEPTOR(int, mallopt
, int cmd
, int value
) { return 0; }
110 INTERCEPTOR(void, malloc_stats
, void) {
111 // FIXME: implement, but don't call REAL(malloc_stats)!
114 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
115 return __sanitizer_get_allocated_size(ptr
);
118 #define ENSURE_DFSAN_INITED() \
120 CHECK(!__dfsan::dfsan_init_is_running); \
121 if (!__dfsan::dfsan_inited) { \
122 __dfsan::dfsan_init(); \
126 #define COMMON_INTERCEPTOR_ENTER(func, ...) \
127 if (__dfsan::dfsan_init_is_running) \
128 return REAL(func)(__VA_ARGS__); \
129 ENSURE_DFSAN_INITED(); \
130 dfsan_set_label(0, __errno_location(), sizeof(int));
132 INTERCEPTOR(void *, mmap
, void *addr
, SIZE_T length
, int prot
, int flags
,
133 int fd
, OFF_T offset
) {
134 if (common_flags()->detect_write_exec
)
135 ReportMmapWriteExec(prot
, flags
);
136 if (!__dfsan::dfsan_inited
)
137 return (void *)internal_mmap(addr
, length
, prot
, flags
, fd
, offset
);
138 COMMON_INTERCEPTOR_ENTER(mmap
, addr
, length
, prot
, flags
, fd
, offset
);
139 void *res
= REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
140 if (res
!= (void *)-1) {
141 dfsan_set_label(0, res
, RoundUpTo(length
, GetPageSizeCached()));
146 INTERCEPTOR(void *, mmap64
, void *addr
, SIZE_T length
, int prot
, int flags
,
147 int fd
, OFF64_T offset
) {
148 if (common_flags()->detect_write_exec
)
149 ReportMmapWriteExec(prot
, flags
);
150 if (!__dfsan::dfsan_inited
)
151 return (void *)internal_mmap(addr
, length
, prot
, flags
, fd
, offset
);
152 COMMON_INTERCEPTOR_ENTER(mmap64
, addr
, length
, prot
, flags
, fd
, offset
);
153 void *res
= REAL(mmap64
)(addr
, length
, prot
, flags
, fd
, offset
);
154 if (res
!= (void *)-1) {
155 dfsan_set_label(0, res
, RoundUpTo(length
, GetPageSizeCached()));
160 INTERCEPTOR(int, munmap
, void *addr
, SIZE_T length
) {
161 if (!__dfsan::dfsan_inited
)
162 return internal_munmap(addr
, length
);
163 COMMON_INTERCEPTOR_ENTER(munmap
, addr
, length
);
164 int res
= REAL(munmap
)(addr
, length
);
166 dfsan_set_label(0, addr
, RoundUpTo(length
, GetPageSizeCached()));
170 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
171 if (__dfsan::DFsanThread *t = __dfsan::GetCurrentThread()) { \
172 *begin = t->tls_begin(); \
173 *end = t->tls_end(); \
177 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
178 dfsan_set_label(0, ptr, size)
180 INTERCEPTOR(void *, __tls_get_addr
, void *arg
) {
181 COMMON_INTERCEPTOR_ENTER(__tls_get_addr
, arg
);
182 void *res
= REAL(__tls_get_addr
)(arg
);
183 uptr tls_begin
, tls_end
;
184 COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin
, &tls_end
);
185 DTLS::DTV
*dtv
= DTLS_on_tls_get_addr(arg
, res
, tls_begin
, tls_end
);
187 // New DTLS block has been allocated.
188 COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv
->beg
, dtv
->size
);
194 void initialize_interceptors() {
195 CHECK(!interceptors_initialized
);
197 INTERCEPT_FUNCTION(aligned_alloc
);
198 INTERCEPT_FUNCTION(calloc
);
199 INTERCEPT_FUNCTION(cfree
);
200 INTERCEPT_FUNCTION(free
);
201 INTERCEPT_FUNCTION(mallinfo
);
202 INTERCEPT_FUNCTION(malloc
);
203 INTERCEPT_FUNCTION(malloc_stats
);
204 INTERCEPT_FUNCTION(malloc_usable_size
);
205 INTERCEPT_FUNCTION(mallopt
);
206 INTERCEPT_FUNCTION(memalign
);
207 INTERCEPT_FUNCTION(mmap
);
208 INTERCEPT_FUNCTION(mmap64
);
209 INTERCEPT_FUNCTION(munmap
);
210 INTERCEPT_FUNCTION(posix_memalign
);
211 INTERCEPT_FUNCTION(pvalloc
);
212 INTERCEPT_FUNCTION(realloc
);
213 INTERCEPT_FUNCTION(reallocarray
);
214 INTERCEPT_FUNCTION(valloc
);
215 INTERCEPT_FUNCTION(__tls_get_addr
);
216 INTERCEPT_FUNCTION(__libc_memalign
);
218 interceptors_initialized
= true;
220 } // namespace __dfsan