1*7c3d14c8STreehugger Robot //===-- msan_interceptors.cc ----------------------------------------------===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of MemorySanitizer.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // Interceptors for standard library functions.
13*7c3d14c8STreehugger Robot //
14*7c3d14c8STreehugger Robot // FIXME: move as many interceptors as possible into
15*7c3d14c8STreehugger Robot // sanitizer_common/sanitizer_common_interceptors.h
16*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
17*7c3d14c8STreehugger Robot
18*7c3d14c8STreehugger Robot #include "interception/interception.h"
19*7c3d14c8STreehugger Robot #include "msan.h"
20*7c3d14c8STreehugger Robot #include "msan_chained_origin_depot.h"
21*7c3d14c8STreehugger Robot #include "msan_origin.h"
22*7c3d14c8STreehugger Robot #include "msan_thread.h"
23*7c3d14c8STreehugger Robot #include "msan_poisoning.h"
24*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_platform_limits_posix.h"
25*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_allocator.h"
26*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_allocator_interface.h"
27*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_allocator_internal.h"
28*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_atomic.h"
29*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
30*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_stackdepot.h"
31*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_libc.h"
32*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_linux.h"
33*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_tls_get_addr.h"
34*7c3d14c8STreehugger Robot
35*7c3d14c8STreehugger Robot #include <stdarg.h>
36*7c3d14c8STreehugger Robot // ACHTUNG! No other system header includes in this file.
37*7c3d14c8STreehugger Robot // Ideally, we should get rid of stdarg.h as well.
38*7c3d14c8STreehugger Robot
39*7c3d14c8STreehugger Robot using namespace __msan;
40*7c3d14c8STreehugger Robot
41*7c3d14c8STreehugger Robot using __sanitizer::memory_order;
42*7c3d14c8STreehugger Robot using __sanitizer::atomic_load;
43*7c3d14c8STreehugger Robot using __sanitizer::atomic_store;
44*7c3d14c8STreehugger Robot using __sanitizer::atomic_uintptr_t;
45*7c3d14c8STreehugger Robot
46*7c3d14c8STreehugger Robot DECLARE_REAL(SIZE_T, strlen, const char *s)
47*7c3d14c8STreehugger Robot DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
48*7c3d14c8STreehugger Robot
49*7c3d14c8STreehugger Robot #if SANITIZER_FREEBSD
50*7c3d14c8STreehugger Robot #define __errno_location __error
51*7c3d14c8STreehugger Robot #endif
52*7c3d14c8STreehugger Robot
53*7c3d14c8STreehugger Robot // True if this is a nested interceptor.
54*7c3d14c8STreehugger Robot static THREADLOCAL int in_interceptor_scope;
55*7c3d14c8STreehugger Robot
56*7c3d14c8STreehugger Robot extern "C" int *__errno_location(void);
57*7c3d14c8STreehugger Robot
58*7c3d14c8STreehugger Robot struct InterceptorScope {
InterceptorScopeInterceptorScope59*7c3d14c8STreehugger Robot InterceptorScope() { ++in_interceptor_scope; }
~InterceptorScopeInterceptorScope60*7c3d14c8STreehugger Robot ~InterceptorScope() { --in_interceptor_scope; }
61*7c3d14c8STreehugger Robot };
62*7c3d14c8STreehugger Robot
IsInInterceptorScope()63*7c3d14c8STreehugger Robot bool IsInInterceptorScope() {
64*7c3d14c8STreehugger Robot return in_interceptor_scope;
65*7c3d14c8STreehugger Robot }
66*7c3d14c8STreehugger Robot
67*7c3d14c8STreehugger Robot #define ENSURE_MSAN_INITED() do { \
68*7c3d14c8STreehugger Robot CHECK(!msan_init_is_running); \
69*7c3d14c8STreehugger Robot if (!msan_inited) { \
70*7c3d14c8STreehugger Robot __msan_init(); \
71*7c3d14c8STreehugger Robot } \
72*7c3d14c8STreehugger Robot } while (0)
73*7c3d14c8STreehugger Robot
74*7c3d14c8STreehugger Robot // Check that [x, x+n) range is unpoisoned.
75*7c3d14c8STreehugger Robot #define CHECK_UNPOISONED_0(x, n) \
76*7c3d14c8STreehugger Robot do { \
77*7c3d14c8STreehugger Robot sptr offset = __msan_test_shadow(x, n); \
78*7c3d14c8STreehugger Robot if (__msan::IsInSymbolizer()) \
79*7c3d14c8STreehugger Robot break; \
80*7c3d14c8STreehugger Robot if (offset >= 0 && __msan::flags()->report_umrs) { \
81*7c3d14c8STreehugger Robot GET_CALLER_PC_BP_SP; \
82*7c3d14c8STreehugger Robot (void) sp; \
83*7c3d14c8STreehugger Robot ReportUMRInsideAddressRange(__func__, x, n, offset); \
84*7c3d14c8STreehugger Robot __msan::PrintWarningWithOrigin( \
85*7c3d14c8STreehugger Robot pc, bp, __msan_get_origin((const char *)x + offset)); \
86*7c3d14c8STreehugger Robot if (__msan::flags()->halt_on_error) { \
87*7c3d14c8STreehugger Robot Printf("Exiting\n"); \
88*7c3d14c8STreehugger Robot Die(); \
89*7c3d14c8STreehugger Robot } \
90*7c3d14c8STreehugger Robot } \
91*7c3d14c8STreehugger Robot } while (0)
92*7c3d14c8STreehugger Robot
93*7c3d14c8STreehugger Robot // Check that [x, x+n) range is unpoisoned unless we are in a nested
94*7c3d14c8STreehugger Robot // interceptor.
95*7c3d14c8STreehugger Robot #define CHECK_UNPOISONED(x, n) \
96*7c3d14c8STreehugger Robot do { \
97*7c3d14c8STreehugger Robot if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
98*7c3d14c8STreehugger Robot } while (0);
99*7c3d14c8STreehugger Robot
100*7c3d14c8STreehugger Robot #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
101*7c3d14c8STreehugger Robot CHECK_UNPOISONED((x), \
102*7c3d14c8STreehugger Robot common_flags()->strict_string_checks ? (len) + 1 : (n) )
103*7c3d14c8STreehugger Robot
104*7c3d14c8STreehugger Robot #define CHECK_UNPOISONED_STRING(x, n) \
105*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
106*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,fread,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)107*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
108*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
109*7c3d14c8STreehugger Robot SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
110*7c3d14c8STreehugger Robot if (res > 0)
111*7c3d14c8STreehugger Robot __msan_unpoison(ptr, res *size);
112*7c3d14c8STreehugger Robot return res;
113*7c3d14c8STreehugger Robot }
114*7c3d14c8STreehugger Robot
115*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,fread_unlocked,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)116*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
117*7c3d14c8STreehugger Robot void *file) {
118*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
119*7c3d14c8STreehugger Robot SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
120*7c3d14c8STreehugger Robot if (res > 0)
121*7c3d14c8STreehugger Robot __msan_unpoison(ptr, res *size);
122*7c3d14c8STreehugger Robot return res;
123*7c3d14c8STreehugger Robot }
124*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
125*7c3d14c8STreehugger Robot #else
126*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
127*7c3d14c8STreehugger Robot #endif
128*7c3d14c8STreehugger Robot
INTERCEPTOR(SSIZE_T,readlink,const char * path,char * buf,SIZE_T bufsiz)129*7c3d14c8STreehugger Robot INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
130*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
131*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(path, 0)
132*7c3d14c8STreehugger Robot SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
133*7c3d14c8STreehugger Robot if (res > 0)
134*7c3d14c8STreehugger Robot __msan_unpoison(buf, res);
135*7c3d14c8STreehugger Robot return res;
136*7c3d14c8STreehugger Robot }
137*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,memcpy,void * dest,const void * src,SIZE_T n)138*7c3d14c8STreehugger Robot INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
139*7c3d14c8STreehugger Robot return __msan_memcpy(dest, src, n);
140*7c3d14c8STreehugger Robot }
141*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,mempcpy,void * dest,const void * src,SIZE_T n)142*7c3d14c8STreehugger Robot INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
143*7c3d14c8STreehugger Robot return (char *)__msan_memcpy(dest, src, n) + n;
144*7c3d14c8STreehugger Robot }
145*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,memccpy,void * dest,const void * src,int c,SIZE_T n)146*7c3d14c8STreehugger Robot INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
147*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
148*7c3d14c8STreehugger Robot void *res = REAL(memccpy)(dest, src, c, n);
149*7c3d14c8STreehugger Robot CHECK(!res || (res >= dest && res <= (char *)dest + n));
150*7c3d14c8STreehugger Robot SIZE_T sz = res ? (char *)res - (char *)dest : n;
151*7c3d14c8STreehugger Robot CHECK_UNPOISONED(src, sz);
152*7c3d14c8STreehugger Robot __msan_unpoison(dest, sz);
153*7c3d14c8STreehugger Robot return res;
154*7c3d14c8STreehugger Robot }
155*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,memmove,void * dest,const void * src,SIZE_T n)156*7c3d14c8STreehugger Robot INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
157*7c3d14c8STreehugger Robot return __msan_memmove(dest, src, n);
158*7c3d14c8STreehugger Robot }
159*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,memset,void * s,int c,SIZE_T n)160*7c3d14c8STreehugger Robot INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
161*7c3d14c8STreehugger Robot return __msan_memset(s, c, n);
162*7c3d14c8STreehugger Robot }
163*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,bcopy,const void * src,void * dest,SIZE_T n)164*7c3d14c8STreehugger Robot INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
165*7c3d14c8STreehugger Robot return __msan_memmove(dest, src, n);
166*7c3d14c8STreehugger Robot }
167*7c3d14c8STreehugger Robot
INTERCEPTOR(int,posix_memalign,void ** memptr,SIZE_T alignment,SIZE_T size)168*7c3d14c8STreehugger Robot INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
169*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
170*7c3d14c8STreehugger Robot CHECK_EQ(alignment & (alignment - 1), 0);
171*7c3d14c8STreehugger Robot CHECK_NE(memptr, 0);
172*7c3d14c8STreehugger Robot *memptr = MsanReallocate(&stack, nullptr, size, alignment, false);
173*7c3d14c8STreehugger Robot CHECK_NE(*memptr, 0);
174*7c3d14c8STreehugger Robot __msan_unpoison(memptr, sizeof(*memptr));
175*7c3d14c8STreehugger Robot return 0;
176*7c3d14c8STreehugger Robot }
177*7c3d14c8STreehugger Robot
178*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,memalign,SIZE_T boundary,SIZE_T size)179*7c3d14c8STreehugger Robot INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) {
180*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
181*7c3d14c8STreehugger Robot CHECK_EQ(boundary & (boundary - 1), 0);
182*7c3d14c8STreehugger Robot void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
183*7c3d14c8STreehugger Robot return ptr;
184*7c3d14c8STreehugger Robot }
185*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
186*7c3d14c8STreehugger Robot #else
187*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MEMALIGN
188*7c3d14c8STreehugger Robot #endif
189*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,aligned_alloc,SIZE_T boundary,SIZE_T size)190*7c3d14c8STreehugger Robot INTERCEPTOR(void *, aligned_alloc, SIZE_T boundary, SIZE_T size) {
191*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
192*7c3d14c8STreehugger Robot CHECK_EQ(boundary & (boundary - 1), 0);
193*7c3d14c8STreehugger Robot void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
194*7c3d14c8STreehugger Robot return ptr;
195*7c3d14c8STreehugger Robot }
196*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,__libc_memalign,SIZE_T boundary,SIZE_T size)197*7c3d14c8STreehugger Robot INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) {
198*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
199*7c3d14c8STreehugger Robot CHECK_EQ(boundary & (boundary - 1), 0);
200*7c3d14c8STreehugger Robot void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
201*7c3d14c8STreehugger Robot DTLS_on_libc_memalign(ptr, size);
202*7c3d14c8STreehugger Robot return ptr;
203*7c3d14c8STreehugger Robot }
204*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,valloc,SIZE_T size)205*7c3d14c8STreehugger Robot INTERCEPTOR(void *, valloc, SIZE_T size) {
206*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
207*7c3d14c8STreehugger Robot void *ptr = MsanReallocate(&stack, nullptr, size, GetPageSizeCached(), false);
208*7c3d14c8STreehugger Robot return ptr;
209*7c3d14c8STreehugger Robot }
210*7c3d14c8STreehugger Robot
211*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,pvalloc,SIZE_T size)212*7c3d14c8STreehugger Robot INTERCEPTOR(void *, pvalloc, SIZE_T size) {
213*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
214*7c3d14c8STreehugger Robot uptr PageSize = GetPageSizeCached();
215*7c3d14c8STreehugger Robot size = RoundUpTo(size, PageSize);
216*7c3d14c8STreehugger Robot if (size == 0) {
217*7c3d14c8STreehugger Robot // pvalloc(0) should allocate one page.
218*7c3d14c8STreehugger Robot size = PageSize;
219*7c3d14c8STreehugger Robot }
220*7c3d14c8STreehugger Robot void *ptr = MsanReallocate(&stack, nullptr, size, PageSize, false);
221*7c3d14c8STreehugger Robot return ptr;
222*7c3d14c8STreehugger Robot }
223*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
224*7c3d14c8STreehugger Robot #else
225*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PVALLOC
226*7c3d14c8STreehugger Robot #endif
227*7c3d14c8STreehugger Robot
INTERCEPTOR(void,free,void * ptr)228*7c3d14c8STreehugger Robot INTERCEPTOR(void, free, void *ptr) {
229*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
230*7c3d14c8STreehugger Robot if (!ptr) return;
231*7c3d14c8STreehugger Robot MsanDeallocate(&stack, ptr);
232*7c3d14c8STreehugger Robot }
233*7c3d14c8STreehugger Robot
234*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(void,cfree,void * ptr)235*7c3d14c8STreehugger Robot INTERCEPTOR(void, cfree, void *ptr) {
236*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
237*7c3d14c8STreehugger Robot if (!ptr) return;
238*7c3d14c8STreehugger Robot MsanDeallocate(&stack, ptr);
239*7c3d14c8STreehugger Robot }
240*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
241*7c3d14c8STreehugger Robot #else
242*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_CFREE
243*7c3d14c8STreehugger Robot #endif
244*7c3d14c8STreehugger Robot
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)245*7c3d14c8STreehugger Robot INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
246*7c3d14c8STreehugger Robot return __sanitizer_get_allocated_size(ptr);
247*7c3d14c8STreehugger Robot }
248*7c3d14c8STreehugger Robot
249*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
250*7c3d14c8STreehugger Robot // This function actually returns a struct by value, but we can't unpoison a
251*7c3d14c8STreehugger Robot // temporary! The following is equivalent on all supported platforms but
252*7c3d14c8STreehugger Robot // aarch64 (which uses a different register for sret value). We have a test
253*7c3d14c8STreehugger Robot // to confirm that.
INTERCEPTOR(void,mallinfo,__sanitizer_mallinfo * sret)254*7c3d14c8STreehugger Robot INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) {
255*7c3d14c8STreehugger Robot #ifdef __aarch64__
256*7c3d14c8STreehugger Robot uptr r8;
257*7c3d14c8STreehugger Robot asm volatile("mov %0,x8" : "=r" (r8));
258*7c3d14c8STreehugger Robot sret = reinterpret_cast<__sanitizer_mallinfo*>(r8);
259*7c3d14c8STreehugger Robot #endif
260*7c3d14c8STreehugger Robot REAL(memset)(sret, 0, sizeof(*sret));
261*7c3d14c8STreehugger Robot __msan_unpoison(sret, sizeof(*sret));
262*7c3d14c8STreehugger Robot }
263*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
264*7c3d14c8STreehugger Robot #else
265*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLINFO
266*7c3d14c8STreehugger Robot #endif
267*7c3d14c8STreehugger Robot
268*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,mallopt,int cmd,int value)269*7c3d14c8STreehugger Robot INTERCEPTOR(int, mallopt, int cmd, int value) {
270*7c3d14c8STreehugger Robot return -1;
271*7c3d14c8STreehugger Robot }
272*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
273*7c3d14c8STreehugger Robot #else
274*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLOPT
275*7c3d14c8STreehugger Robot #endif
276*7c3d14c8STreehugger Robot
277*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(void,malloc_stats,void)278*7c3d14c8STreehugger Robot INTERCEPTOR(void, malloc_stats, void) {
279*7c3d14c8STreehugger Robot // FIXME: implement, but don't call REAL(malloc_stats)!
280*7c3d14c8STreehugger Robot }
281*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
282*7c3d14c8STreehugger Robot #else
283*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
284*7c3d14c8STreehugger Robot #endif
285*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strcpy,char * dest,const char * src)286*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT
287*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
288*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
289*7c3d14c8STreehugger Robot SIZE_T n = REAL(strlen)(src);
290*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(src + n, 0);
291*7c3d14c8STreehugger Robot char *res = REAL(strcpy)(dest, src); // NOLINT
292*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, n + 1, &stack);
293*7c3d14c8STreehugger Robot return res;
294*7c3d14c8STreehugger Robot }
295*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strncpy,char * dest,const char * src,SIZE_T n)296*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT
297*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
298*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
299*7c3d14c8STreehugger Robot SIZE_T copy_size = REAL(strnlen)(src, n);
300*7c3d14c8STreehugger Robot if (copy_size < n)
301*7c3d14c8STreehugger Robot copy_size++; // trailing \0
302*7c3d14c8STreehugger Robot char *res = REAL(strncpy)(dest, src, n); // NOLINT
303*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, copy_size, &stack);
304*7c3d14c8STreehugger Robot __msan_unpoison(dest + copy_size, n - copy_size);
305*7c3d14c8STreehugger Robot return res;
306*7c3d14c8STreehugger Robot }
307*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,stpcpy,char * dest,const char * src)308*7c3d14c8STreehugger Robot INTERCEPTOR(char *, stpcpy, char *dest, const char *src) { // NOLINT
309*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
310*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
311*7c3d14c8STreehugger Robot SIZE_T n = REAL(strlen)(src);
312*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(src + n, 0);
313*7c3d14c8STreehugger Robot char *res = REAL(stpcpy)(dest, src); // NOLINT
314*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, n + 1, &stack);
315*7c3d14c8STreehugger Robot return res;
316*7c3d14c8STreehugger Robot }
317*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strdup,char * src)318*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strdup, char *src) {
319*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
320*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
321*7c3d14c8STreehugger Robot // On FreeBSD strdup() leverages strlen().
322*7c3d14c8STreehugger Robot InterceptorScope interceptor_scope;
323*7c3d14c8STreehugger Robot SIZE_T n = REAL(strlen)(src);
324*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(src + n, 0);
325*7c3d14c8STreehugger Robot char *res = REAL(strdup)(src);
326*7c3d14c8STreehugger Robot CopyShadowAndOrigin(res, src, n + 1, &stack);
327*7c3d14c8STreehugger Robot return res;
328*7c3d14c8STreehugger Robot }
329*7c3d14c8STreehugger Robot
330*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,__strdup,char * src)331*7c3d14c8STreehugger Robot INTERCEPTOR(char *, __strdup, char *src) {
332*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
333*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
334*7c3d14c8STreehugger Robot SIZE_T n = REAL(strlen)(src);
335*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(src + n, 0);
336*7c3d14c8STreehugger Robot char *res = REAL(__strdup)(src);
337*7c3d14c8STreehugger Robot CopyShadowAndOrigin(res, src, n + 1, &stack);
338*7c3d14c8STreehugger Robot return res;
339*7c3d14c8STreehugger Robot }
340*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
341*7c3d14c8STreehugger Robot #else
342*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRDUP
343*7c3d14c8STreehugger Robot #endif
344*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strndup,char * src,SIZE_T n)345*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
346*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
347*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
348*7c3d14c8STreehugger Robot // On FreeBSD strndup() leverages strnlen().
349*7c3d14c8STreehugger Robot InterceptorScope interceptor_scope;
350*7c3d14c8STreehugger Robot SIZE_T copy_size = REAL(strnlen)(src, n);
351*7c3d14c8STreehugger Robot char *res = REAL(strndup)(src, n);
352*7c3d14c8STreehugger Robot CopyShadowAndOrigin(res, src, copy_size, &stack);
353*7c3d14c8STreehugger Robot __msan_unpoison(res + copy_size, 1); // \0
354*7c3d14c8STreehugger Robot return res;
355*7c3d14c8STreehugger Robot }
356*7c3d14c8STreehugger Robot
357*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,__strndup,char * src,SIZE_T n)358*7c3d14c8STreehugger Robot INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
359*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
360*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
361*7c3d14c8STreehugger Robot SIZE_T copy_size = REAL(strnlen)(src, n);
362*7c3d14c8STreehugger Robot char *res = REAL(__strndup)(src, n);
363*7c3d14c8STreehugger Robot CopyShadowAndOrigin(res, src, copy_size, &stack);
364*7c3d14c8STreehugger Robot __msan_unpoison(res + copy_size, 1); // \0
365*7c3d14c8STreehugger Robot return res;
366*7c3d14c8STreehugger Robot }
367*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
368*7c3d14c8STreehugger Robot #else
369*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRNDUP
370*7c3d14c8STreehugger Robot #endif
371*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,gcvt,double number,SIZE_T ndigit,char * buf)372*7c3d14c8STreehugger Robot INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
373*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
374*7c3d14c8STreehugger Robot char *res = REAL(gcvt)(number, ndigit, buf);
375*7c3d14c8STreehugger Robot SIZE_T n = REAL(strlen)(buf);
376*7c3d14c8STreehugger Robot __msan_unpoison(buf, n + 1);
377*7c3d14c8STreehugger Robot return res;
378*7c3d14c8STreehugger Robot }
379*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strcat,char * dest,const char * src)380*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT
381*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
382*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
383*7c3d14c8STreehugger Robot SIZE_T src_size = REAL(strlen)(src);
384*7c3d14c8STreehugger Robot SIZE_T dest_size = REAL(strlen)(dest);
385*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(src + src_size, 0);
386*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(dest + dest_size, 0);
387*7c3d14c8STreehugger Robot char *res = REAL(strcat)(dest, src); // NOLINT
388*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
389*7c3d14c8STreehugger Robot return res;
390*7c3d14c8STreehugger Robot }
391*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,strncat,char * dest,const char * src,SIZE_T n)392*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT
393*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
394*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
395*7c3d14c8STreehugger Robot SIZE_T dest_size = REAL(strlen)(dest);
396*7c3d14c8STreehugger Robot SIZE_T copy_size = REAL(strnlen)(src, n);
397*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(dest + dest_size, 0);
398*7c3d14c8STreehugger Robot char *res = REAL(strncat)(dest, src, n); // NOLINT
399*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
400*7c3d14c8STreehugger Robot __msan_unpoison(dest + dest_size + copy_size, 1); // \0
401*7c3d14c8STreehugger Robot return res;
402*7c3d14c8STreehugger Robot }
403*7c3d14c8STreehugger Robot
404*7c3d14c8STreehugger Robot // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
405*7c3d14c8STreehugger Robot // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
406*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
407*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED(); \
408*7c3d14c8STreehugger Robot ret_type res = REAL(func)(__VA_ARGS__); \
409*7c3d14c8STreehugger Robot __msan_unpoison(endptr, sizeof(*endptr)); \
410*7c3d14c8STreehugger Robot return res;
411*7c3d14c8STreehugger Robot
412*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
413*7c3d14c8STreehugger Robot INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
414*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
415*7c3d14c8STreehugger Robot }
416*7c3d14c8STreehugger Robot
417*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
418*7c3d14c8STreehugger Robot INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
419*7c3d14c8STreehugger Robot int base) { \
420*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
421*7c3d14c8STreehugger Robot }
422*7c3d14c8STreehugger Robot
423*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
424*7c3d14c8STreehugger Robot INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
425*7c3d14c8STreehugger Robot void *loc) { \
426*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
427*7c3d14c8STreehugger Robot }
428*7c3d14c8STreehugger Robot
429*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
430*7c3d14c8STreehugger Robot INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
431*7c3d14c8STreehugger Robot int base, void *loc) { \
432*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
433*7c3d14c8STreehugger Robot }
434*7c3d14c8STreehugger Robot
435*7c3d14c8STreehugger Robot #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
436*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO(ret_type, func, char_type) \
437*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
438*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
439*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
440*7c3d14c8STreehugger Robot
441*7c3d14c8STreehugger Robot #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
442*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
443*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
444*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
445*7c3d14c8STreehugger Robot INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
446*7c3d14c8STreehugger Robot
INTERCEPTORS_STRTO(double,strtod,char)447*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(double, strtod, char) // NOLINT
448*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(float, strtof, char) // NOLINT
449*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(long double, strtold, char) // NOLINT
450*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(long, strtol, char) // NOLINT
451*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(long long, strtoll, char) // NOLINT
452*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char) // NOLINT
453*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char) // NOLINT
454*7c3d14c8STreehugger Robot
455*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(double, wcstod, wchar_t) // NOLINT
456*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(float, wcstof, wchar_t) // NOLINT
457*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO(long double, wcstold, wchar_t) // NOLINT
458*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t) // NOLINT
459*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t) // NOLINT
460*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t) // NOLINT
461*7c3d14c8STreehugger Robot INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t) // NOLINT
462*7c3d14c8STreehugger Robot
463*7c3d14c8STreehugger Robot #define INTERCEPT_STRTO(func) \
464*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(func); \
465*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(func##_l); \
466*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(__##func##_l); \
467*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(__##func##_internal);
468*7c3d14c8STreehugger Robot
469*7c3d14c8STreehugger Robot
470*7c3d14c8STreehugger Robot // FIXME: support *wprintf in common format interceptors.
471*7c3d14c8STreehugger Robot INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
472*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
473*7c3d14c8STreehugger Robot int res = REAL(vswprintf)(str, size, format, ap);
474*7c3d14c8STreehugger Robot if (res >= 0) {
475*7c3d14c8STreehugger Robot __msan_unpoison(str, 4 * (res + 1));
476*7c3d14c8STreehugger Robot }
477*7c3d14c8STreehugger Robot return res;
478*7c3d14c8STreehugger Robot }
479*7c3d14c8STreehugger Robot
INTERCEPTOR(int,swprintf,void * str,uptr size,void * format,...)480*7c3d14c8STreehugger Robot INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
481*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
482*7c3d14c8STreehugger Robot va_list ap;
483*7c3d14c8STreehugger Robot va_start(ap, format);
484*7c3d14c8STreehugger Robot int res = vswprintf(str, size, format, ap);
485*7c3d14c8STreehugger Robot va_end(ap);
486*7c3d14c8STreehugger Robot return res;
487*7c3d14c8STreehugger Robot }
488*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,strxfrm,char * dest,const char * src,SIZE_T n)489*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T n) {
490*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
491*7c3d14c8STreehugger Robot CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
492*7c3d14c8STreehugger Robot SIZE_T res = REAL(strxfrm)(dest, src, n);
493*7c3d14c8STreehugger Robot if (res < n) __msan_unpoison(dest, res + 1);
494*7c3d14c8STreehugger Robot return res;
495*7c3d14c8STreehugger Robot }
496*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,strxfrm_l,char * dest,const char * src,SIZE_T n,void * loc)497*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T n,
498*7c3d14c8STreehugger Robot void *loc) {
499*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
500*7c3d14c8STreehugger Robot CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
501*7c3d14c8STreehugger Robot SIZE_T res = REAL(strxfrm_l)(dest, src, n, loc);
502*7c3d14c8STreehugger Robot if (res < n) __msan_unpoison(dest, res + 1);
503*7c3d14c8STreehugger Robot return res;
504*7c3d14c8STreehugger Robot }
505*7c3d14c8STreehugger Robot
506*7c3d14c8STreehugger Robot #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
507*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED(); \
508*7c3d14c8STreehugger Robot ret_type res = REAL(func)(s, __VA_ARGS__); \
509*7c3d14c8STreehugger Robot if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
510*7c3d14c8STreehugger Robot return res;
511*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,strftime,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm)512*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
513*7c3d14c8STreehugger Robot __sanitizer_tm *tm) {
514*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
515*7c3d14c8STreehugger Robot }
516*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)517*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
518*7c3d14c8STreehugger Robot __sanitizer_tm *tm, void *loc) {
519*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
520*7c3d14c8STreehugger Robot }
521*7c3d14c8STreehugger Robot
522*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,__strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)523*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
524*7c3d14c8STreehugger Robot __sanitizer_tm *tm, void *loc) {
525*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
526*7c3d14c8STreehugger Robot loc);
527*7c3d14c8STreehugger Robot }
528*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
529*7c3d14c8STreehugger Robot #else
530*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
531*7c3d14c8STreehugger Robot #endif
532*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,wcsftime,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm)533*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
534*7c3d14c8STreehugger Robot __sanitizer_tm *tm) {
535*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
536*7c3d14c8STreehugger Robot }
537*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)538*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
539*7c3d14c8STreehugger Robot __sanitizer_tm *tm, void *loc) {
540*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
541*7c3d14c8STreehugger Robot loc);
542*7c3d14c8STreehugger Robot }
543*7c3d14c8STreehugger Robot
544*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,__wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)545*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
546*7c3d14c8STreehugger Robot __sanitizer_tm *tm, void *loc) {
547*7c3d14c8STreehugger Robot INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
548*7c3d14c8STreehugger Robot loc);
549*7c3d14c8STreehugger Robot }
550*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
551*7c3d14c8STreehugger Robot #else
552*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
553*7c3d14c8STreehugger Robot #endif
554*7c3d14c8STreehugger Robot
INTERCEPTOR(int,mbtowc,wchar_t * dest,const char * src,SIZE_T n)555*7c3d14c8STreehugger Robot INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
556*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
557*7c3d14c8STreehugger Robot int res = REAL(mbtowc)(dest, src, n);
558*7c3d14c8STreehugger Robot if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
559*7c3d14c8STreehugger Robot return res;
560*7c3d14c8STreehugger Robot }
561*7c3d14c8STreehugger Robot
INTERCEPTOR(int,mbrtowc,wchar_t * dest,const char * src,SIZE_T n,void * ps)562*7c3d14c8STreehugger Robot INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
563*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
564*7c3d14c8STreehugger Robot SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
565*7c3d14c8STreehugger Robot if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
566*7c3d14c8STreehugger Robot return res;
567*7c3d14c8STreehugger Robot }
568*7c3d14c8STreehugger Robot
INTERCEPTOR(SIZE_T,wcslen,const wchar_t * s)569*7c3d14c8STreehugger Robot INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
570*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
571*7c3d14c8STreehugger Robot SIZE_T res = REAL(wcslen)(s);
572*7c3d14c8STreehugger Robot CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
573*7c3d14c8STreehugger Robot return res;
574*7c3d14c8STreehugger Robot }
575*7c3d14c8STreehugger Robot
576*7c3d14c8STreehugger Robot // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *,wcschr,void * s,wchar_t wc,void * ps)577*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
578*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
579*7c3d14c8STreehugger Robot wchar_t *res = REAL(wcschr)(s, wc, ps);
580*7c3d14c8STreehugger Robot return res;
581*7c3d14c8STreehugger Robot }
582*7c3d14c8STreehugger Robot
583*7c3d14c8STreehugger Robot // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *,wcscpy,wchar_t * dest,const wchar_t * src)584*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
585*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
586*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
587*7c3d14c8STreehugger Robot wchar_t *res = REAL(wcscpy)(dest, src);
588*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
589*7c3d14c8STreehugger Robot &stack);
590*7c3d14c8STreehugger Robot return res;
591*7c3d14c8STreehugger Robot }
592*7c3d14c8STreehugger Robot
593*7c3d14c8STreehugger Robot // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
INTERCEPTOR(wchar_t *,wmemcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)594*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
595*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
596*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
597*7c3d14c8STreehugger Robot wchar_t *res = REAL(wmemcpy)(dest, src, n);
598*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
599*7c3d14c8STreehugger Robot return res;
600*7c3d14c8STreehugger Robot }
601*7c3d14c8STreehugger Robot
INTERCEPTOR(wchar_t *,wmempcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)602*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
603*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
604*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
605*7c3d14c8STreehugger Robot wchar_t *res = REAL(wmempcpy)(dest, src, n);
606*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
607*7c3d14c8STreehugger Robot return res;
608*7c3d14c8STreehugger Robot }
609*7c3d14c8STreehugger Robot
INTERCEPTOR(wchar_t *,wmemset,wchar_t * s,wchar_t c,SIZE_T n)610*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
611*7c3d14c8STreehugger Robot CHECK(MEM_IS_APP(s));
612*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
613*7c3d14c8STreehugger Robot wchar_t *res = REAL(wmemset)(s, c, n);
614*7c3d14c8STreehugger Robot __msan_unpoison(s, n * sizeof(wchar_t));
615*7c3d14c8STreehugger Robot return res;
616*7c3d14c8STreehugger Robot }
617*7c3d14c8STreehugger Robot
INTERCEPTOR(wchar_t *,wmemmove,wchar_t * dest,const wchar_t * src,SIZE_T n)618*7c3d14c8STreehugger Robot INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
619*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
620*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
621*7c3d14c8STreehugger Robot wchar_t *res = REAL(wmemmove)(dest, src, n);
622*7c3d14c8STreehugger Robot MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
623*7c3d14c8STreehugger Robot return res;
624*7c3d14c8STreehugger Robot }
625*7c3d14c8STreehugger Robot
INTERCEPTOR(int,wcscmp,const wchar_t * s1,const wchar_t * s2)626*7c3d14c8STreehugger Robot INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
627*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
628*7c3d14c8STreehugger Robot int res = REAL(wcscmp)(s1, s2);
629*7c3d14c8STreehugger Robot return res;
630*7c3d14c8STreehugger Robot }
631*7c3d14c8STreehugger Robot
INTERCEPTOR(int,gettimeofday,void * tv,void * tz)632*7c3d14c8STreehugger Robot INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
633*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
634*7c3d14c8STreehugger Robot int res = REAL(gettimeofday)(tv, tz);
635*7c3d14c8STreehugger Robot if (tv)
636*7c3d14c8STreehugger Robot __msan_unpoison(tv, 16);
637*7c3d14c8STreehugger Robot if (tz)
638*7c3d14c8STreehugger Robot __msan_unpoison(tz, 8);
639*7c3d14c8STreehugger Robot return res;
640*7c3d14c8STreehugger Robot }
641*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,fcvt,double x,int a,int * b,int * c)642*7c3d14c8STreehugger Robot INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
643*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
644*7c3d14c8STreehugger Robot char *res = REAL(fcvt)(x, a, b, c);
645*7c3d14c8STreehugger Robot __msan_unpoison(b, sizeof(*b));
646*7c3d14c8STreehugger Robot __msan_unpoison(c, sizeof(*c));
647*7c3d14c8STreehugger Robot if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
648*7c3d14c8STreehugger Robot return res;
649*7c3d14c8STreehugger Robot }
650*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,getenv,char * name)651*7c3d14c8STreehugger Robot INTERCEPTOR(char *, getenv, char *name) {
652*7c3d14c8STreehugger Robot if (msan_init_is_running)
653*7c3d14c8STreehugger Robot return REAL(getenv)(name);
654*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
655*7c3d14c8STreehugger Robot char *res = REAL(getenv)(name);
656*7c3d14c8STreehugger Robot if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
657*7c3d14c8STreehugger Robot return res;
658*7c3d14c8STreehugger Robot }
659*7c3d14c8STreehugger Robot
660*7c3d14c8STreehugger Robot extern char **environ;
661*7c3d14c8STreehugger Robot
UnpoisonEnviron()662*7c3d14c8STreehugger Robot static void UnpoisonEnviron() {
663*7c3d14c8STreehugger Robot char **envp = environ;
664*7c3d14c8STreehugger Robot for (; *envp; ++envp) {
665*7c3d14c8STreehugger Robot __msan_unpoison(envp, sizeof(*envp));
666*7c3d14c8STreehugger Robot __msan_unpoison(*envp, REAL(strlen)(*envp) + 1);
667*7c3d14c8STreehugger Robot }
668*7c3d14c8STreehugger Robot // Trailing NULL pointer.
669*7c3d14c8STreehugger Robot __msan_unpoison(envp, sizeof(*envp));
670*7c3d14c8STreehugger Robot }
671*7c3d14c8STreehugger Robot
INTERCEPTOR(int,setenv,const char * name,const char * value,int overwrite)672*7c3d14c8STreehugger Robot INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
673*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
674*7c3d14c8STreehugger Robot CHECK_UNPOISONED_STRING(name, 0)
675*7c3d14c8STreehugger Robot int res = REAL(setenv)(name, value, overwrite);
676*7c3d14c8STreehugger Robot if (!res) UnpoisonEnviron();
677*7c3d14c8STreehugger Robot return res;
678*7c3d14c8STreehugger Robot }
679*7c3d14c8STreehugger Robot
INTERCEPTOR(int,putenv,char * string)680*7c3d14c8STreehugger Robot INTERCEPTOR(int, putenv, char *string) {
681*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
682*7c3d14c8STreehugger Robot int res = REAL(putenv)(string);
683*7c3d14c8STreehugger Robot if (!res) UnpoisonEnviron();
684*7c3d14c8STreehugger Robot return res;
685*7c3d14c8STreehugger Robot }
686*7c3d14c8STreehugger Robot
687*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstat,int magic,int fd,void * buf)688*7c3d14c8STreehugger Robot INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
689*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
690*7c3d14c8STreehugger Robot int res = REAL(__fxstat)(magic, fd, buf);
691*7c3d14c8STreehugger Robot if (!res)
692*7c3d14c8STreehugger Robot __msan_unpoison(buf, __sanitizer::struct_stat_sz);
693*7c3d14c8STreehugger Robot return res;
694*7c3d14c8STreehugger Robot }
695*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTAT INTERCEPT_FUNCTION(__fxstat)
696*7c3d14c8STreehugger Robot #else
697*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTAT
698*7c3d14c8STreehugger Robot #endif
699*7c3d14c8STreehugger Robot
700*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstat64,int magic,int fd,void * buf)701*7c3d14c8STreehugger Robot INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
702*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
703*7c3d14c8STreehugger Robot int res = REAL(__fxstat64)(magic, fd, buf);
704*7c3d14c8STreehugger Robot if (!res)
705*7c3d14c8STreehugger Robot __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
706*7c3d14c8STreehugger Robot return res;
707*7c3d14c8STreehugger Robot }
708*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTAT64 INTERCEPT_FUNCTION(__fxstat64)
709*7c3d14c8STreehugger Robot #else
710*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTAT64
711*7c3d14c8STreehugger Robot #endif
712*7c3d14c8STreehugger Robot
713*7c3d14c8STreehugger Robot #if SANITIZER_FREEBSD
INTERCEPTOR(int,fstatat,int fd,char * pathname,void * buf,int flags)714*7c3d14c8STreehugger Robot INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
715*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
716*7c3d14c8STreehugger Robot int res = REAL(fstatat)(fd, pathname, buf, flags);
717*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
718*7c3d14c8STreehugger Robot return res;
719*7c3d14c8STreehugger Robot }
720*7c3d14c8STreehugger Robot # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat)
721*7c3d14c8STreehugger Robot #else
INTERCEPTOR(int,__fxstatat,int magic,int fd,char * pathname,void * buf,int flags)722*7c3d14c8STreehugger Robot INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
723*7c3d14c8STreehugger Robot int flags) {
724*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
725*7c3d14c8STreehugger Robot int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
726*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
727*7c3d14c8STreehugger Robot return res;
728*7c3d14c8STreehugger Robot }
729*7c3d14c8STreehugger Robot # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat)
730*7c3d14c8STreehugger Robot #endif
731*7c3d14c8STreehugger Robot
732*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstatat64,int magic,int fd,char * pathname,void * buf,int flags)733*7c3d14c8STreehugger Robot INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
734*7c3d14c8STreehugger Robot int flags) {
735*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
736*7c3d14c8STreehugger Robot int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
737*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
738*7c3d14c8STreehugger Robot return res;
739*7c3d14c8STreehugger Robot }
740*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTATAT64 INTERCEPT_FUNCTION(__fxstatat64)
741*7c3d14c8STreehugger Robot #else
742*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT___FXSTATAT64
743*7c3d14c8STreehugger Robot #endif
744*7c3d14c8STreehugger Robot
INTERCEPTOR(int,pipe,int pipefd[2])745*7c3d14c8STreehugger Robot INTERCEPTOR(int, pipe, int pipefd[2]) {
746*7c3d14c8STreehugger Robot if (msan_init_is_running)
747*7c3d14c8STreehugger Robot return REAL(pipe)(pipefd);
748*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
749*7c3d14c8STreehugger Robot int res = REAL(pipe)(pipefd);
750*7c3d14c8STreehugger Robot if (!res)
751*7c3d14c8STreehugger Robot __msan_unpoison(pipefd, sizeof(int[2]));
752*7c3d14c8STreehugger Robot return res;
753*7c3d14c8STreehugger Robot }
754*7c3d14c8STreehugger Robot
INTERCEPTOR(int,pipe2,int pipefd[2],int flags)755*7c3d14c8STreehugger Robot INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
756*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
757*7c3d14c8STreehugger Robot int res = REAL(pipe2)(pipefd, flags);
758*7c3d14c8STreehugger Robot if (!res)
759*7c3d14c8STreehugger Robot __msan_unpoison(pipefd, sizeof(int[2]));
760*7c3d14c8STreehugger Robot return res;
761*7c3d14c8STreehugger Robot }
762*7c3d14c8STreehugger Robot
INTERCEPTOR(int,socketpair,int domain,int type,int protocol,int sv[2])763*7c3d14c8STreehugger Robot INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
764*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
765*7c3d14c8STreehugger Robot int res = REAL(socketpair)(domain, type, protocol, sv);
766*7c3d14c8STreehugger Robot if (!res)
767*7c3d14c8STreehugger Robot __msan_unpoison(sv, sizeof(int[2]));
768*7c3d14c8STreehugger Robot return res;
769*7c3d14c8STreehugger Robot }
770*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,fgets,char * s,int size,void * stream)771*7c3d14c8STreehugger Robot INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
772*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
773*7c3d14c8STreehugger Robot char *res = REAL(fgets)(s, size, stream);
774*7c3d14c8STreehugger Robot if (res)
775*7c3d14c8STreehugger Robot __msan_unpoison(s, REAL(strlen)(s) + 1);
776*7c3d14c8STreehugger Robot return res;
777*7c3d14c8STreehugger Robot }
778*7c3d14c8STreehugger Robot
779*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,fgets_unlocked,char * s,int size,void * stream)780*7c3d14c8STreehugger Robot INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
781*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
782*7c3d14c8STreehugger Robot char *res = REAL(fgets_unlocked)(s, size, stream);
783*7c3d14c8STreehugger Robot if (res)
784*7c3d14c8STreehugger Robot __msan_unpoison(s, REAL(strlen)(s) + 1);
785*7c3d14c8STreehugger Robot return res;
786*7c3d14c8STreehugger Robot }
787*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
788*7c3d14c8STreehugger Robot #else
789*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
790*7c3d14c8STreehugger Robot #endif
791*7c3d14c8STreehugger Robot
INTERCEPTOR(int,getrlimit,int resource,void * rlim)792*7c3d14c8STreehugger Robot INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
793*7c3d14c8STreehugger Robot if (msan_init_is_running)
794*7c3d14c8STreehugger Robot return REAL(getrlimit)(resource, rlim);
795*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
796*7c3d14c8STreehugger Robot int res = REAL(getrlimit)(resource, rlim);
797*7c3d14c8STreehugger Robot if (!res)
798*7c3d14c8STreehugger Robot __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
799*7c3d14c8STreehugger Robot return res;
800*7c3d14c8STreehugger Robot }
801*7c3d14c8STreehugger Robot
802*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,getrlimit64,int resource,void * rlim)803*7c3d14c8STreehugger Robot INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
804*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
805*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
806*7c3d14c8STreehugger Robot int res = REAL(getrlimit64)(resource, rlim);
807*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
808*7c3d14c8STreehugger Robot return res;
809*7c3d14c8STreehugger Robot }
810*7c3d14c8STreehugger Robot
INTERCEPTOR(int,prlimit,int pid,int resource,void * new_rlimit,void * old_rlimit)811*7c3d14c8STreehugger Robot INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
812*7c3d14c8STreehugger Robot void *old_rlimit) {
813*7c3d14c8STreehugger Robot if (msan_init_is_running)
814*7c3d14c8STreehugger Robot return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
815*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
816*7c3d14c8STreehugger Robot CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
817*7c3d14c8STreehugger Robot int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
818*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
819*7c3d14c8STreehugger Robot return res;
820*7c3d14c8STreehugger Robot }
821*7c3d14c8STreehugger Robot
INTERCEPTOR(int,prlimit64,int pid,int resource,void * new_rlimit,void * old_rlimit)822*7c3d14c8STreehugger Robot INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
823*7c3d14c8STreehugger Robot void *old_rlimit) {
824*7c3d14c8STreehugger Robot if (msan_init_is_running)
825*7c3d14c8STreehugger Robot return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
826*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
827*7c3d14c8STreehugger Robot CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
828*7c3d14c8STreehugger Robot int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
829*7c3d14c8STreehugger Robot if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
830*7c3d14c8STreehugger Robot return res;
831*7c3d14c8STreehugger Robot }
832*7c3d14c8STreehugger Robot
833*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
834*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
835*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
836*7c3d14c8STreehugger Robot #else
837*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
838*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PRLIMIT
839*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
840*7c3d14c8STreehugger Robot #endif
841*7c3d14c8STreehugger Robot
842*7c3d14c8STreehugger Robot #if SANITIZER_FREEBSD
843*7c3d14c8STreehugger Robot // FreeBSD's <sys/utsname.h> define uname() as
844*7c3d14c8STreehugger Robot // static __inline int uname(struct utsname *name) {
845*7c3d14c8STreehugger Robot // return __xuname(SYS_NMLN, (void*)name);
846*7c3d14c8STreehugger Robot // }
INTERCEPTOR(int,__xuname,int size,void * utsname)847*7c3d14c8STreehugger Robot INTERCEPTOR(int, __xuname, int size, void *utsname) {
848*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
849*7c3d14c8STreehugger Robot int res = REAL(__xuname)(size, utsname);
850*7c3d14c8STreehugger Robot if (!res)
851*7c3d14c8STreehugger Robot __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
852*7c3d14c8STreehugger Robot return res;
853*7c3d14c8STreehugger Robot }
854*7c3d14c8STreehugger Robot #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname)
855*7c3d14c8STreehugger Robot #else
INTERCEPTOR(int,uname,struct utsname * utsname)856*7c3d14c8STreehugger Robot INTERCEPTOR(int, uname, struct utsname *utsname) {
857*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
858*7c3d14c8STreehugger Robot int res = REAL(uname)(utsname);
859*7c3d14c8STreehugger Robot if (!res)
860*7c3d14c8STreehugger Robot __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
861*7c3d14c8STreehugger Robot return res;
862*7c3d14c8STreehugger Robot }
863*7c3d14c8STreehugger Robot #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname)
864*7c3d14c8STreehugger Robot #endif
865*7c3d14c8STreehugger Robot
INTERCEPTOR(int,gethostname,char * name,SIZE_T len)866*7c3d14c8STreehugger Robot INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
867*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
868*7c3d14c8STreehugger Robot int res = REAL(gethostname)(name, len);
869*7c3d14c8STreehugger Robot if (!res) {
870*7c3d14c8STreehugger Robot SIZE_T real_len = REAL(strnlen)(name, len);
871*7c3d14c8STreehugger Robot if (real_len < len)
872*7c3d14c8STreehugger Robot ++real_len;
873*7c3d14c8STreehugger Robot __msan_unpoison(name, real_len);
874*7c3d14c8STreehugger Robot }
875*7c3d14c8STreehugger Robot return res;
876*7c3d14c8STreehugger Robot }
877*7c3d14c8STreehugger Robot
878*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)879*7c3d14c8STreehugger Robot INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
880*7c3d14c8STreehugger Robot int timeout) {
881*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
882*7c3d14c8STreehugger Robot int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
883*7c3d14c8STreehugger Robot if (res > 0) {
884*7c3d14c8STreehugger Robot __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
885*7c3d14c8STreehugger Robot }
886*7c3d14c8STreehugger Robot return res;
887*7c3d14c8STreehugger Robot }
888*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
889*7c3d14c8STreehugger Robot #else
890*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
891*7c3d14c8STreehugger Robot #endif
892*7c3d14c8STreehugger Robot
893*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(int,epoll_pwait,int epfd,void * events,int maxevents,int timeout,void * sigmask)894*7c3d14c8STreehugger Robot INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
895*7c3d14c8STreehugger Robot int timeout, void *sigmask) {
896*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
897*7c3d14c8STreehugger Robot int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
898*7c3d14c8STreehugger Robot if (res > 0) {
899*7c3d14c8STreehugger Robot __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
900*7c3d14c8STreehugger Robot }
901*7c3d14c8STreehugger Robot return res;
902*7c3d14c8STreehugger Robot }
903*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
904*7c3d14c8STreehugger Robot #else
905*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
906*7c3d14c8STreehugger Robot #endif
907*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,calloc,SIZE_T nmemb,SIZE_T size)908*7c3d14c8STreehugger Robot INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
909*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
910*7c3d14c8STreehugger Robot if (UNLIKELY(!msan_inited)) {
911*7c3d14c8STreehugger Robot // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
912*7c3d14c8STreehugger Robot const SIZE_T kCallocPoolSize = 1024;
913*7c3d14c8STreehugger Robot static uptr calloc_memory_for_dlsym[kCallocPoolSize];
914*7c3d14c8STreehugger Robot static SIZE_T allocated;
915*7c3d14c8STreehugger Robot SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
916*7c3d14c8STreehugger Robot void *mem = (void*)&calloc_memory_for_dlsym[allocated];
917*7c3d14c8STreehugger Robot allocated += size_in_words;
918*7c3d14c8STreehugger Robot CHECK(allocated < kCallocPoolSize);
919*7c3d14c8STreehugger Robot return mem;
920*7c3d14c8STreehugger Robot }
921*7c3d14c8STreehugger Robot return MsanCalloc(&stack, nmemb, size);
922*7c3d14c8STreehugger Robot }
923*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,realloc,void * ptr,SIZE_T size)924*7c3d14c8STreehugger Robot INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
925*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
926*7c3d14c8STreehugger Robot return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
927*7c3d14c8STreehugger Robot }
928*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,malloc,SIZE_T size)929*7c3d14c8STreehugger Robot INTERCEPTOR(void *, malloc, SIZE_T size) {
930*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
931*7c3d14c8STreehugger Robot return MsanReallocate(&stack, nullptr, size, sizeof(u64), false);
932*7c3d14c8STreehugger Robot }
933*7c3d14c8STreehugger Robot
__msan_allocated_memory(const void * data,uptr size)934*7c3d14c8STreehugger Robot void __msan_allocated_memory(const void *data, uptr size) {
935*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
936*7c3d14c8STreehugger Robot if (flags()->poison_in_malloc) {
937*7c3d14c8STreehugger Robot stack.tag = STACK_TRACE_TAG_POISON;
938*7c3d14c8STreehugger Robot PoisonMemory(data, size, &stack);
939*7c3d14c8STreehugger Robot }
940*7c3d14c8STreehugger Robot }
941*7c3d14c8STreehugger Robot
__msan_copy_shadow(void * dest,const void * src,uptr n)942*7c3d14c8STreehugger Robot void __msan_copy_shadow(void *dest, const void *src, uptr n) {
943*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
944*7c3d14c8STreehugger Robot MoveShadowAndOrigin(dest, src, n, &stack);
945*7c3d14c8STreehugger Robot }
946*7c3d14c8STreehugger Robot
__sanitizer_dtor_callback(const void * data,uptr size)947*7c3d14c8STreehugger Robot void __sanitizer_dtor_callback(const void *data, uptr size) {
948*7c3d14c8STreehugger Robot GET_MALLOC_STACK_TRACE;
949*7c3d14c8STreehugger Robot if (flags()->poison_in_dtor) {
950*7c3d14c8STreehugger Robot stack.tag = STACK_TRACE_TAG_POISON;
951*7c3d14c8STreehugger Robot PoisonMemory(data, size, &stack);
952*7c3d14c8STreehugger Robot }
953*7c3d14c8STreehugger Robot }
954*7c3d14c8STreehugger Robot
INTERCEPTOR(void *,mmap,void * addr,SIZE_T length,int prot,int flags,int fd,OFF_T offset)955*7c3d14c8STreehugger Robot INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
956*7c3d14c8STreehugger Robot int fd, OFF_T offset) {
957*7c3d14c8STreehugger Robot if (msan_init_is_running)
958*7c3d14c8STreehugger Robot return REAL(mmap)(addr, length, prot, flags, fd, offset);
959*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
960*7c3d14c8STreehugger Robot if (addr && !MEM_IS_APP(addr)) {
961*7c3d14c8STreehugger Robot if (flags & map_fixed) {
962*7c3d14c8STreehugger Robot *__errno_location() = errno_EINVAL;
963*7c3d14c8STreehugger Robot return (void *)-1;
964*7c3d14c8STreehugger Robot } else {
965*7c3d14c8STreehugger Robot addr = nullptr;
966*7c3d14c8STreehugger Robot }
967*7c3d14c8STreehugger Robot }
968*7c3d14c8STreehugger Robot void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
969*7c3d14c8STreehugger Robot if (res != (void*)-1)
970*7c3d14c8STreehugger Robot __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
971*7c3d14c8STreehugger Robot return res;
972*7c3d14c8STreehugger Robot }
973*7c3d14c8STreehugger Robot
974*7c3d14c8STreehugger Robot #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,mmap64,void * addr,SIZE_T length,int prot,int flags,int fd,OFF64_T offset)975*7c3d14c8STreehugger Robot INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
976*7c3d14c8STreehugger Robot int fd, OFF64_T offset) {
977*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
978*7c3d14c8STreehugger Robot if (addr && !MEM_IS_APP(addr)) {
979*7c3d14c8STreehugger Robot if (flags & map_fixed) {
980*7c3d14c8STreehugger Robot *__errno_location() = errno_EINVAL;
981*7c3d14c8STreehugger Robot return (void *)-1;
982*7c3d14c8STreehugger Robot } else {
983*7c3d14c8STreehugger Robot addr = nullptr;
984*7c3d14c8STreehugger Robot }
985*7c3d14c8STreehugger Robot }
986*7c3d14c8STreehugger Robot void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
987*7c3d14c8STreehugger Robot if (res != (void*)-1)
988*7c3d14c8STreehugger Robot __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
989*7c3d14c8STreehugger Robot return res;
990*7c3d14c8STreehugger Robot }
991*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
992*7c3d14c8STreehugger Robot #else
993*7c3d14c8STreehugger Robot #define MSAN_MAYBE_INTERCEPT_MMAP64
994*7c3d14c8STreehugger Robot #endif
995*7c3d14c8STreehugger Robot
INTERCEPTOR(int,getrusage,int who,void * usage)996*7c3d14c8STreehugger Robot INTERCEPTOR(int, getrusage, int who, void *usage) {
997*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
998*7c3d14c8STreehugger Robot int res = REAL(getrusage)(who, usage);
999*7c3d14c8STreehugger Robot if (res == 0) {
1000*7c3d14c8STreehugger Robot __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
1001*7c3d14c8STreehugger Robot }
1002*7c3d14c8STreehugger Robot return res;
1003*7c3d14c8STreehugger Robot }
1004*7c3d14c8STreehugger Robot
1005*7c3d14c8STreehugger Robot class SignalHandlerScope {
1006*7c3d14c8STreehugger Robot public:
SignalHandlerScope()1007*7c3d14c8STreehugger Robot SignalHandlerScope() {
1008*7c3d14c8STreehugger Robot if (MsanThread *t = GetCurrentThread())
1009*7c3d14c8STreehugger Robot t->EnterSignalHandler();
1010*7c3d14c8STreehugger Robot }
~SignalHandlerScope()1011*7c3d14c8STreehugger Robot ~SignalHandlerScope() {
1012*7c3d14c8STreehugger Robot if (MsanThread *t = GetCurrentThread())
1013*7c3d14c8STreehugger Robot t->LeaveSignalHandler();
1014*7c3d14c8STreehugger Robot }
1015*7c3d14c8STreehugger Robot };
1016*7c3d14c8STreehugger Robot
1017*7c3d14c8STreehugger Robot // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1018*7c3d14c8STreehugger Robot // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1019*7c3d14c8STreehugger Robot // the signal handler.
1020*7c3d14c8STreehugger Robot const int kMaxSignals = 1024;
1021*7c3d14c8STreehugger Robot static atomic_uintptr_t sigactions[kMaxSignals];
1022*7c3d14c8STreehugger Robot static StaticSpinMutex sigactions_mu;
1023*7c3d14c8STreehugger Robot
SignalHandler(int signo)1024*7c3d14c8STreehugger Robot static void SignalHandler(int signo) {
1025*7c3d14c8STreehugger Robot SignalHandlerScope signal_handler_scope;
1026*7c3d14c8STreehugger Robot ScopedThreadLocalStateBackup stlsb;
1027*7c3d14c8STreehugger Robot UnpoisonParam(1);
1028*7c3d14c8STreehugger Robot
1029*7c3d14c8STreehugger Robot typedef void (*signal_cb)(int x);
1030*7c3d14c8STreehugger Robot signal_cb cb =
1031*7c3d14c8STreehugger Robot (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1032*7c3d14c8STreehugger Robot cb(signo);
1033*7c3d14c8STreehugger Robot }
1034*7c3d14c8STreehugger Robot
SignalAction(int signo,void * si,void * uc)1035*7c3d14c8STreehugger Robot static void SignalAction(int signo, void *si, void *uc) {
1036*7c3d14c8STreehugger Robot SignalHandlerScope signal_handler_scope;
1037*7c3d14c8STreehugger Robot ScopedThreadLocalStateBackup stlsb;
1038*7c3d14c8STreehugger Robot UnpoisonParam(3);
1039*7c3d14c8STreehugger Robot __msan_unpoison(si, sizeof(__sanitizer_sigaction));
1040*7c3d14c8STreehugger Robot __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
1041*7c3d14c8STreehugger Robot
1042*7c3d14c8STreehugger Robot typedef void (*sigaction_cb)(int, void *, void *);
1043*7c3d14c8STreehugger Robot sigaction_cb cb =
1044*7c3d14c8STreehugger Robot (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1045*7c3d14c8STreehugger Robot cb(signo, si, uc);
1046*7c3d14c8STreehugger Robot }
1047*7c3d14c8STreehugger Robot
INTERCEPTOR(int,sigaction,int signo,const __sanitizer_sigaction * act,__sanitizer_sigaction * oldact)1048*7c3d14c8STreehugger Robot INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
1049*7c3d14c8STreehugger Robot __sanitizer_sigaction *oldact) {
1050*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1051*7c3d14c8STreehugger Robot // FIXME: check that *act is unpoisoned.
1052*7c3d14c8STreehugger Robot // That requires intercepting all of sigemptyset, sigfillset, etc.
1053*7c3d14c8STreehugger Robot int res;
1054*7c3d14c8STreehugger Robot if (flags()->wrap_signals) {
1055*7c3d14c8STreehugger Robot SpinMutexLock lock(&sigactions_mu);
1056*7c3d14c8STreehugger Robot CHECK_LT(signo, kMaxSignals);
1057*7c3d14c8STreehugger Robot uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1058*7c3d14c8STreehugger Robot __sanitizer_sigaction new_act;
1059*7c3d14c8STreehugger Robot __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1060*7c3d14c8STreehugger Robot if (act) {
1061*7c3d14c8STreehugger Robot REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1062*7c3d14c8STreehugger Robot uptr cb = (uptr)pnew_act->sigaction;
1063*7c3d14c8STreehugger Robot uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1064*7c3d14c8STreehugger Robot ? (uptr)SignalAction
1065*7c3d14c8STreehugger Robot : (uptr)SignalHandler;
1066*7c3d14c8STreehugger Robot if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1067*7c3d14c8STreehugger Robot atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1068*7c3d14c8STreehugger Robot pnew_act->sigaction = (void (*)(int, void *, void *))new_cb;
1069*7c3d14c8STreehugger Robot }
1070*7c3d14c8STreehugger Robot }
1071*7c3d14c8STreehugger Robot res = REAL(sigaction)(signo, pnew_act, oldact);
1072*7c3d14c8STreehugger Robot if (res == 0 && oldact) {
1073*7c3d14c8STreehugger Robot uptr cb = (uptr)oldact->sigaction;
1074*7c3d14c8STreehugger Robot if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1075*7c3d14c8STreehugger Robot oldact->sigaction = (void (*)(int, void *, void *))old_cb;
1076*7c3d14c8STreehugger Robot }
1077*7c3d14c8STreehugger Robot }
1078*7c3d14c8STreehugger Robot } else {
1079*7c3d14c8STreehugger Robot res = REAL(sigaction)(signo, act, oldact);
1080*7c3d14c8STreehugger Robot }
1081*7c3d14c8STreehugger Robot
1082*7c3d14c8STreehugger Robot if (res == 0 && oldact) {
1083*7c3d14c8STreehugger Robot __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1084*7c3d14c8STreehugger Robot }
1085*7c3d14c8STreehugger Robot return res;
1086*7c3d14c8STreehugger Robot }
1087*7c3d14c8STreehugger Robot
INTERCEPTOR(int,signal,int signo,uptr cb)1088*7c3d14c8STreehugger Robot INTERCEPTOR(int, signal, int signo, uptr cb) {
1089*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1090*7c3d14c8STreehugger Robot if (flags()->wrap_signals) {
1091*7c3d14c8STreehugger Robot CHECK_LT(signo, kMaxSignals);
1092*7c3d14c8STreehugger Robot SpinMutexLock lock(&sigactions_mu);
1093*7c3d14c8STreehugger Robot if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1094*7c3d14c8STreehugger Robot atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1095*7c3d14c8STreehugger Robot cb = (uptr) SignalHandler;
1096*7c3d14c8STreehugger Robot }
1097*7c3d14c8STreehugger Robot return REAL(signal)(signo, cb);
1098*7c3d14c8STreehugger Robot } else {
1099*7c3d14c8STreehugger Robot return REAL(signal)(signo, cb);
1100*7c3d14c8STreehugger Robot }
1101*7c3d14c8STreehugger Robot }
1102*7c3d14c8STreehugger Robot
1103*7c3d14c8STreehugger Robot extern "C" int pthread_attr_init(void *attr);
1104*7c3d14c8STreehugger Robot extern "C" int pthread_attr_destroy(void *attr);
1105*7c3d14c8STreehugger Robot
MsanThreadStartFunc(void * arg)1106*7c3d14c8STreehugger Robot static void *MsanThreadStartFunc(void *arg) {
1107*7c3d14c8STreehugger Robot MsanThread *t = (MsanThread *)arg;
1108*7c3d14c8STreehugger Robot SetCurrentThread(t);
1109*7c3d14c8STreehugger Robot return t->ThreadStart();
1110*7c3d14c8STreehugger Robot }
1111*7c3d14c8STreehugger Robot
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)1112*7c3d14c8STreehugger Robot INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1113*7c3d14c8STreehugger Robot void * param) {
1114*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED(); // for GetTlsSize()
1115*7c3d14c8STreehugger Robot __sanitizer_pthread_attr_t myattr;
1116*7c3d14c8STreehugger Robot if (!attr) {
1117*7c3d14c8STreehugger Robot pthread_attr_init(&myattr);
1118*7c3d14c8STreehugger Robot attr = &myattr;
1119*7c3d14c8STreehugger Robot }
1120*7c3d14c8STreehugger Robot
1121*7c3d14c8STreehugger Robot AdjustStackSize(attr);
1122*7c3d14c8STreehugger Robot
1123*7c3d14c8STreehugger Robot MsanThread *t = MsanThread::Create(callback, param);
1124*7c3d14c8STreehugger Robot
1125*7c3d14c8STreehugger Robot int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1126*7c3d14c8STreehugger Robot
1127*7c3d14c8STreehugger Robot if (attr == &myattr)
1128*7c3d14c8STreehugger Robot pthread_attr_destroy(&myattr);
1129*7c3d14c8STreehugger Robot if (!res) {
1130*7c3d14c8STreehugger Robot __msan_unpoison(th, __sanitizer::pthread_t_sz);
1131*7c3d14c8STreehugger Robot }
1132*7c3d14c8STreehugger Robot return res;
1133*7c3d14c8STreehugger Robot }
1134*7c3d14c8STreehugger Robot
INTERCEPTOR(int,pthread_key_create,__sanitizer_pthread_key_t * key,void (* dtor)(void * value))1135*7c3d14c8STreehugger Robot INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1136*7c3d14c8STreehugger Robot void (*dtor)(void *value)) {
1137*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1138*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1139*7c3d14c8STreehugger Robot int res = REAL(pthread_key_create)(key, dtor);
1140*7c3d14c8STreehugger Robot if (!res && key)
1141*7c3d14c8STreehugger Robot __msan_unpoison(key, sizeof(*key));
1142*7c3d14c8STreehugger Robot return res;
1143*7c3d14c8STreehugger Robot }
1144*7c3d14c8STreehugger Robot
INTERCEPTOR(int,pthread_join,void * th,void ** retval)1145*7c3d14c8STreehugger Robot INTERCEPTOR(int, pthread_join, void *th, void **retval) {
1146*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1147*7c3d14c8STreehugger Robot int res = REAL(pthread_join)(th, retval);
1148*7c3d14c8STreehugger Robot if (!res && retval)
1149*7c3d14c8STreehugger Robot __msan_unpoison(retval, sizeof(*retval));
1150*7c3d14c8STreehugger Robot return res;
1151*7c3d14c8STreehugger Robot }
1152*7c3d14c8STreehugger Robot
1153*7c3d14c8STreehugger Robot extern char *tzname[2];
1154*7c3d14c8STreehugger Robot
INTERCEPTOR(void,tzset,int fake)1155*7c3d14c8STreehugger Robot INTERCEPTOR(void, tzset, int fake) {
1156*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1157*7c3d14c8STreehugger Robot REAL(tzset)(fake);
1158*7c3d14c8STreehugger Robot if (tzname[0])
1159*7c3d14c8STreehugger Robot __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1);
1160*7c3d14c8STreehugger Robot if (tzname[1])
1161*7c3d14c8STreehugger Robot __msan_unpoison(tzname[1], REAL(strlen)(tzname[1]) + 1);
1162*7c3d14c8STreehugger Robot return;
1163*7c3d14c8STreehugger Robot }
1164*7c3d14c8STreehugger Robot
1165*7c3d14c8STreehugger Robot struct MSanAtExitRecord {
1166*7c3d14c8STreehugger Robot void (*func)(void *arg);
1167*7c3d14c8STreehugger Robot void *arg;
1168*7c3d14c8STreehugger Robot };
1169*7c3d14c8STreehugger Robot
MSanAtExitWrapper(void * arg)1170*7c3d14c8STreehugger Robot void MSanAtExitWrapper(void *arg) {
1171*7c3d14c8STreehugger Robot UnpoisonParam(1);
1172*7c3d14c8STreehugger Robot MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1173*7c3d14c8STreehugger Robot r->func(r->arg);
1174*7c3d14c8STreehugger Robot InternalFree(r);
1175*7c3d14c8STreehugger Robot }
1176*7c3d14c8STreehugger Robot
1177*7c3d14c8STreehugger Robot // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)1178*7c3d14c8STreehugger Robot INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1179*7c3d14c8STreehugger Robot void *dso_handle) {
1180*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1181*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1182*7c3d14c8STreehugger Robot MSanAtExitRecord *r =
1183*7c3d14c8STreehugger Robot (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1184*7c3d14c8STreehugger Robot r->func = func;
1185*7c3d14c8STreehugger Robot r->arg = arg;
1186*7c3d14c8STreehugger Robot return REAL(__cxa_atexit)(MSanAtExitWrapper, r, dso_handle);
1187*7c3d14c8STreehugger Robot }
1188*7c3d14c8STreehugger Robot
DECLARE_REAL(int,shmctl,int shmid,int cmd,void * buf)1189*7c3d14c8STreehugger Robot DECLARE_REAL(int, shmctl, int shmid, int cmd, void *buf)
1190*7c3d14c8STreehugger Robot
1191*7c3d14c8STreehugger Robot INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1192*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1193*7c3d14c8STreehugger Robot void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1194*7c3d14c8STreehugger Robot if (p != (void *)-1) {
1195*7c3d14c8STreehugger Robot __sanitizer_shmid_ds ds;
1196*7c3d14c8STreehugger Robot int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1197*7c3d14c8STreehugger Robot if (!res) {
1198*7c3d14c8STreehugger Robot __msan_unpoison(p, ds.shm_segsz);
1199*7c3d14c8STreehugger Robot }
1200*7c3d14c8STreehugger Robot }
1201*7c3d14c8STreehugger Robot return p;
1202*7c3d14c8STreehugger Robot }
1203*7c3d14c8STreehugger Robot
BeforeFork()1204*7c3d14c8STreehugger Robot static void BeforeFork() {
1205*7c3d14c8STreehugger Robot StackDepotLockAll();
1206*7c3d14c8STreehugger Robot ChainedOriginDepotLockAll();
1207*7c3d14c8STreehugger Robot }
1208*7c3d14c8STreehugger Robot
AfterFork()1209*7c3d14c8STreehugger Robot static void AfterFork() {
1210*7c3d14c8STreehugger Robot ChainedOriginDepotUnlockAll();
1211*7c3d14c8STreehugger Robot StackDepotUnlockAll();
1212*7c3d14c8STreehugger Robot }
1213*7c3d14c8STreehugger Robot
INTERCEPTOR(int,fork,void)1214*7c3d14c8STreehugger Robot INTERCEPTOR(int, fork, void) {
1215*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1216*7c3d14c8STreehugger Robot BeforeFork();
1217*7c3d14c8STreehugger Robot int pid = REAL(fork)();
1218*7c3d14c8STreehugger Robot AfterFork();
1219*7c3d14c8STreehugger Robot return pid;
1220*7c3d14c8STreehugger Robot }
1221*7c3d14c8STreehugger Robot
INTERCEPTOR(int,openpty,int * amaster,int * aslave,char * name,const void * termp,const void * winp)1222*7c3d14c8STreehugger Robot INTERCEPTOR(int, openpty, int *amaster, int *aslave, char *name,
1223*7c3d14c8STreehugger Robot const void *termp, const void *winp) {
1224*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1225*7c3d14c8STreehugger Robot InterceptorScope interceptor_scope;
1226*7c3d14c8STreehugger Robot int res = REAL(openpty)(amaster, aslave, name, termp, winp);
1227*7c3d14c8STreehugger Robot if (!res) {
1228*7c3d14c8STreehugger Robot __msan_unpoison(amaster, sizeof(*amaster));
1229*7c3d14c8STreehugger Robot __msan_unpoison(aslave, sizeof(*aslave));
1230*7c3d14c8STreehugger Robot }
1231*7c3d14c8STreehugger Robot return res;
1232*7c3d14c8STreehugger Robot }
1233*7c3d14c8STreehugger Robot
INTERCEPTOR(int,forkpty,int * amaster,char * name,const void * termp,const void * winp)1234*7c3d14c8STreehugger Robot INTERCEPTOR(int, forkpty, int *amaster, char *name, const void *termp,
1235*7c3d14c8STreehugger Robot const void *winp) {
1236*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1237*7c3d14c8STreehugger Robot InterceptorScope interceptor_scope;
1238*7c3d14c8STreehugger Robot int res = REAL(forkpty)(amaster, name, termp, winp);
1239*7c3d14c8STreehugger Robot if (res != -1)
1240*7c3d14c8STreehugger Robot __msan_unpoison(amaster, sizeof(*amaster));
1241*7c3d14c8STreehugger Robot return res;
1242*7c3d14c8STreehugger Robot }
1243*7c3d14c8STreehugger Robot
1244*7c3d14c8STreehugger Robot struct MSanInterceptorContext {
1245*7c3d14c8STreehugger Robot bool in_interceptor_scope;
1246*7c3d14c8STreehugger Robot };
1247*7c3d14c8STreehugger Robot
1248*7c3d14c8STreehugger Robot namespace __msan {
1249*7c3d14c8STreehugger Robot
OnExit()1250*7c3d14c8STreehugger Robot int OnExit() {
1251*7c3d14c8STreehugger Robot // FIXME: ask frontend whether we need to return failure.
1252*7c3d14c8STreehugger Robot return 0;
1253*7c3d14c8STreehugger Robot }
1254*7c3d14c8STreehugger Robot
1255*7c3d14c8STreehugger Robot } // namespace __msan
1256*7c3d14c8STreehugger Robot
1257*7c3d14c8STreehugger Robot // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1258*7c3d14c8STreehugger Robot // interceptors.
1259*7c3d14c8STreehugger Robot #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1260*7c3d14c8STreehugger Robot do { \
1261*7c3d14c8STreehugger Robot if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1262*7c3d14c8STreehugger Robot CHECK_UNPOISONED_0(x, n); \
1263*7c3d14c8STreehugger Robot } while (0)
1264*7c3d14c8STreehugger Robot
1265*7c3d14c8STreehugger Robot #define MSAN_INTERCEPT_FUNC(name) \
1266*7c3d14c8STreehugger Robot do { \
1267*7c3d14c8STreehugger Robot if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
1268*7c3d14c8STreehugger Robot VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \
1269*7c3d14c8STreehugger Robot } while (0)
1270*7c3d14c8STreehugger Robot
1271*7c3d14c8STreehugger Robot #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1272*7c3d14c8STreehugger Robot do { \
1273*7c3d14c8STreehugger Robot if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \
1274*7c3d14c8STreehugger Robot VReport( \
1275*7c3d14c8STreehugger Robot 1, "MemorySanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
1276*7c3d14c8STreehugger Robot } while (0)
1277*7c3d14c8STreehugger Robot
1278*7c3d14c8STreehugger Robot #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1279*7c3d14c8STreehugger Robot #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1280*7c3d14c8STreehugger Robot MSAN_INTERCEPT_FUNC_VER(name, ver)
1281*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1282*7c3d14c8STreehugger Robot UnpoisonParam(count)
1283*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1284*7c3d14c8STreehugger Robot __msan_unpoison(ptr, size)
1285*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1286*7c3d14c8STreehugger Robot CHECK_UNPOISONED_CTX(ctx, ptr, size)
1287*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1288*7c3d14c8STreehugger Robot __msan_unpoison(ptr, size)
1289*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1290*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \
1291*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED(); \
1292*7c3d14c8STreehugger Robot MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1293*7c3d14c8STreehugger Robot ctx = (void *)&msan_ctx; \
1294*7c3d14c8STreehugger Robot (void)ctx; \
1295*7c3d14c8STreehugger Robot InterceptorScope interceptor_scope; \
1296*7c3d14c8STreehugger Robot __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */
1297*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1298*7c3d14c8STreehugger Robot do { \
1299*7c3d14c8STreehugger Robot } while (false)
1300*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1301*7c3d14c8STreehugger Robot do { \
1302*7c3d14c8STreehugger Robot } while (false)
1303*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1304*7c3d14c8STreehugger Robot do { \
1305*7c3d14c8STreehugger Robot } while (false)
1306*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1307*7c3d14c8STreehugger Robot do { \
1308*7c3d14c8STreehugger Robot } while (false)
1309*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1310*7c3d14c8STreehugger Robot do { \
1311*7c3d14c8STreehugger Robot } while (false) // FIXME
1312*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1313*7c3d14c8STreehugger Robot do { \
1314*7c3d14c8STreehugger Robot } while (false) // FIXME
1315*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1316*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1317*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1318*7c3d14c8STreehugger Robot do { \
1319*7c3d14c8STreehugger Robot link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1320*7c3d14c8STreehugger Robot if (filename && map) \
1321*7c3d14c8STreehugger Robot ForEachMappedRegion(map, __msan_unpoison); \
1322*7c3d14c8STreehugger Robot } while (false)
1323*7c3d14c8STreehugger Robot
1324*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1325*7c3d14c8STreehugger Robot if (MsanThread *t = GetCurrentThread()) { \
1326*7c3d14c8STreehugger Robot *begin = t->tls_begin(); \
1327*7c3d14c8STreehugger Robot *end = t->tls_end(); \
1328*7c3d14c8STreehugger Robot } else { \
1329*7c3d14c8STreehugger Robot *begin = *end = 0; \
1330*7c3d14c8STreehugger Robot }
1331*7c3d14c8STreehugger Robot
1332*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_platform_interceptors.h"
1333*7c3d14c8STreehugger Robot // Msan needs custom handling of these:
1334*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_MEMSET
1335*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_MEMMOVE
1336*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_MEMCPY
1337*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common_interceptors.inc"
1338*7c3d14c8STreehugger Robot
1339*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1340*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1341*7c3d14c8STreehugger Robot do { \
1342*7c3d14c8STreehugger Robot } while (false)
1343*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1344*7c3d14c8STreehugger Robot do { \
1345*7c3d14c8STreehugger Robot } while (false)
1346*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1347*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common_syscalls.inc"
1348*7c3d14c8STreehugger Robot
1349*7c3d14c8STreehugger Robot struct dlinfo {
1350*7c3d14c8STreehugger Robot char *dli_fname;
1351*7c3d14c8STreehugger Robot void *dli_fbase;
1352*7c3d14c8STreehugger Robot char *dli_sname;
1353*7c3d14c8STreehugger Robot void *dli_saddr;
1354*7c3d14c8STreehugger Robot };
1355*7c3d14c8STreehugger Robot
INTERCEPTOR(int,dladdr,void * addr,dlinfo * info)1356*7c3d14c8STreehugger Robot INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
1357*7c3d14c8STreehugger Robot void *ctx;
1358*7c3d14c8STreehugger Robot COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1359*7c3d14c8STreehugger Robot int res = REAL(dladdr)(addr, info);
1360*7c3d14c8STreehugger Robot if (res != 0) {
1361*7c3d14c8STreehugger Robot __msan_unpoison(info, sizeof(*info));
1362*7c3d14c8STreehugger Robot if (info->dli_fname)
1363*7c3d14c8STreehugger Robot __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
1364*7c3d14c8STreehugger Robot if (info->dli_sname)
1365*7c3d14c8STreehugger Robot __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
1366*7c3d14c8STreehugger Robot }
1367*7c3d14c8STreehugger Robot return res;
1368*7c3d14c8STreehugger Robot }
1369*7c3d14c8STreehugger Robot
INTERCEPTOR(char *,dlerror,int fake)1370*7c3d14c8STreehugger Robot INTERCEPTOR(char *, dlerror, int fake) {
1371*7c3d14c8STreehugger Robot void *ctx;
1372*7c3d14c8STreehugger Robot COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1373*7c3d14c8STreehugger Robot char *res = REAL(dlerror)(fake);
1374*7c3d14c8STreehugger Robot if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
1375*7c3d14c8STreehugger Robot return res;
1376*7c3d14c8STreehugger Robot }
1377*7c3d14c8STreehugger Robot
1378*7c3d14c8STreehugger Robot typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1379*7c3d14c8STreehugger Robot void *data);
1380*7c3d14c8STreehugger Robot struct dl_iterate_phdr_data {
1381*7c3d14c8STreehugger Robot dl_iterate_phdr_cb callback;
1382*7c3d14c8STreehugger Robot void *data;
1383*7c3d14c8STreehugger Robot };
1384*7c3d14c8STreehugger Robot
msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info * info,SIZE_T size,void * data)1385*7c3d14c8STreehugger Robot static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1386*7c3d14c8STreehugger Robot void *data) {
1387*7c3d14c8STreehugger Robot if (info) {
1388*7c3d14c8STreehugger Robot __msan_unpoison(info, size);
1389*7c3d14c8STreehugger Robot if (info->dlpi_phdr && info->dlpi_phnum)
1390*7c3d14c8STreehugger Robot __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1391*7c3d14c8STreehugger Robot if (info->dlpi_name)
1392*7c3d14c8STreehugger Robot __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
1393*7c3d14c8STreehugger Robot }
1394*7c3d14c8STreehugger Robot dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1395*7c3d14c8STreehugger Robot UnpoisonParam(3);
1396*7c3d14c8STreehugger Robot return cbdata->callback(info, size, cbdata->data);
1397*7c3d14c8STreehugger Robot }
1398*7c3d14c8STreehugger Robot
INTERCEPTOR(int,dl_iterate_phdr,dl_iterate_phdr_cb callback,void * data)1399*7c3d14c8STreehugger Robot INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1400*7c3d14c8STreehugger Robot void *ctx;
1401*7c3d14c8STreehugger Robot COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1402*7c3d14c8STreehugger Robot dl_iterate_phdr_data cbdata;
1403*7c3d14c8STreehugger Robot cbdata.callback = callback;
1404*7c3d14c8STreehugger Robot cbdata.data = data;
1405*7c3d14c8STreehugger Robot int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1406*7c3d14c8STreehugger Robot return res;
1407*7c3d14c8STreehugger Robot }
1408*7c3d14c8STreehugger Robot
1409*7c3d14c8STreehugger Robot // These interface functions reside here so that they can use
1410*7c3d14c8STreehugger Robot // REAL(memset), etc.
__msan_unpoison(const void * a,uptr size)1411*7c3d14c8STreehugger Robot void __msan_unpoison(const void *a, uptr size) {
1412*7c3d14c8STreehugger Robot if (!MEM_IS_APP(a)) return;
1413*7c3d14c8STreehugger Robot SetShadow(a, size, 0);
1414*7c3d14c8STreehugger Robot }
1415*7c3d14c8STreehugger Robot
__msan_poison(const void * a,uptr size)1416*7c3d14c8STreehugger Robot void __msan_poison(const void *a, uptr size) {
1417*7c3d14c8STreehugger Robot if (!MEM_IS_APP(a)) return;
1418*7c3d14c8STreehugger Robot SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1419*7c3d14c8STreehugger Robot }
1420*7c3d14c8STreehugger Robot
__msan_poison_stack(void * a,uptr size)1421*7c3d14c8STreehugger Robot void __msan_poison_stack(void *a, uptr size) {
1422*7c3d14c8STreehugger Robot if (!MEM_IS_APP(a)) return;
1423*7c3d14c8STreehugger Robot SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1424*7c3d14c8STreehugger Robot }
1425*7c3d14c8STreehugger Robot
__msan_clear_and_unpoison(void * a,uptr size)1426*7c3d14c8STreehugger Robot void __msan_clear_and_unpoison(void *a, uptr size) {
1427*7c3d14c8STreehugger Robot REAL(memset)(a, 0, size);
1428*7c3d14c8STreehugger Robot SetShadow(a, size, 0);
1429*7c3d14c8STreehugger Robot }
1430*7c3d14c8STreehugger Robot
__msan_memcpy(void * dest,const void * src,SIZE_T n)1431*7c3d14c8STreehugger Robot void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1432*7c3d14c8STreehugger Robot if (!msan_inited) return internal_memcpy(dest, src, n);
1433*7c3d14c8STreehugger Robot if (msan_init_is_running || __msan::IsInSymbolizer())
1434*7c3d14c8STreehugger Robot return REAL(memcpy)(dest, src, n);
1435*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1436*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
1437*7c3d14c8STreehugger Robot void *res = REAL(memcpy)(dest, src, n);
1438*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dest, src, n, &stack);
1439*7c3d14c8STreehugger Robot return res;
1440*7c3d14c8STreehugger Robot }
1441*7c3d14c8STreehugger Robot
__msan_memset(void * s,int c,SIZE_T n)1442*7c3d14c8STreehugger Robot void *__msan_memset(void *s, int c, SIZE_T n) {
1443*7c3d14c8STreehugger Robot if (!msan_inited) return internal_memset(s, c, n);
1444*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(memset)(s, c, n);
1445*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1446*7c3d14c8STreehugger Robot void *res = REAL(memset)(s, c, n);
1447*7c3d14c8STreehugger Robot __msan_unpoison(s, n);
1448*7c3d14c8STreehugger Robot return res;
1449*7c3d14c8STreehugger Robot }
1450*7c3d14c8STreehugger Robot
__msan_memmove(void * dest,const void * src,SIZE_T n)1451*7c3d14c8STreehugger Robot void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1452*7c3d14c8STreehugger Robot if (!msan_inited) return internal_memmove(dest, src, n);
1453*7c3d14c8STreehugger Robot if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1454*7c3d14c8STreehugger Robot ENSURE_MSAN_INITED();
1455*7c3d14c8STreehugger Robot GET_STORE_STACK_TRACE;
1456*7c3d14c8STreehugger Robot void *res = REAL(memmove)(dest, src, n);
1457*7c3d14c8STreehugger Robot MoveShadowAndOrigin(dest, src, n, &stack);
1458*7c3d14c8STreehugger Robot return res;
1459*7c3d14c8STreehugger Robot }
1460*7c3d14c8STreehugger Robot
__msan_unpoison_string(const char * s)1461*7c3d14c8STreehugger Robot void __msan_unpoison_string(const char* s) {
1462*7c3d14c8STreehugger Robot if (!MEM_IS_APP(s)) return;
1463*7c3d14c8STreehugger Robot __msan_unpoison(s, REAL(strlen)(s) + 1);
1464*7c3d14c8STreehugger Robot }
1465*7c3d14c8STreehugger Robot
1466*7c3d14c8STreehugger Robot namespace __msan {
1467*7c3d14c8STreehugger Robot
InitializeInterceptors()1468*7c3d14c8STreehugger Robot void InitializeInterceptors() {
1469*7c3d14c8STreehugger Robot static int inited = 0;
1470*7c3d14c8STreehugger Robot CHECK_EQ(inited, 0);
1471*7c3d14c8STreehugger Robot InitializeCommonInterceptors();
1472*7c3d14c8STreehugger Robot
1473*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(mmap);
1474*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_MMAP64;
1475*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(posix_memalign);
1476*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_MEMALIGN;
1477*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(__libc_memalign);
1478*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(valloc);
1479*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_PVALLOC;
1480*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(malloc);
1481*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(calloc);
1482*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(realloc);
1483*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(free);
1484*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_CFREE;
1485*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(malloc_usable_size);
1486*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_MALLINFO;
1487*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_MALLOPT;
1488*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1489*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(fread);
1490*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1491*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(readlink);
1492*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(memcpy);
1493*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(memccpy);
1494*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(mempcpy);
1495*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(memset);
1496*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(memmove);
1497*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(bcopy);
1498*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wmemset);
1499*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wmemcpy);
1500*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wmempcpy);
1501*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wmemmove);
1502*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strcpy); // NOLINT
1503*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(stpcpy); // NOLINT
1504*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strdup);
1505*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___STRDUP;
1506*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strndup);
1507*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___STRNDUP;
1508*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strncpy); // NOLINT
1509*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(gcvt);
1510*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strcat); // NOLINT
1511*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strncat); // NOLINT
1512*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtod);
1513*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtof);
1514*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtold);
1515*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtol);
1516*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtoul);
1517*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtoll);
1518*7c3d14c8STreehugger Robot INTERCEPT_STRTO(strtoull);
1519*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstod);
1520*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstof);
1521*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstold);
1522*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstol);
1523*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstoul);
1524*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstoll);
1525*7c3d14c8STreehugger Robot INTERCEPT_STRTO(wcstoull);
1526*7c3d14c8STreehugger Robot #ifdef SANITIZER_NLDBL_VERSION
1527*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1528*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1529*7c3d14c8STreehugger Robot #else
1530*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(vswprintf);
1531*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(swprintf);
1532*7c3d14c8STreehugger Robot #endif
1533*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strxfrm);
1534*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strxfrm_l);
1535*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strftime);
1536*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(strftime_l);
1537*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1538*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcsftime);
1539*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcsftime_l);
1540*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1541*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(mbtowc);
1542*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(mbrtowc);
1543*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcslen);
1544*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcschr);
1545*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcscpy);
1546*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(wcscmp);
1547*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(getenv);
1548*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(setenv);
1549*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(putenv);
1550*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(gettimeofday);
1551*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(fcvt);
1552*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___FXSTAT;
1553*7c3d14c8STreehugger Robot MSAN_INTERCEPT_FSTATAT;
1554*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___FXSTAT64;
1555*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1556*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(pipe);
1557*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(pipe2);
1558*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(socketpair);
1559*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(fgets);
1560*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1561*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(getrlimit);
1562*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1563*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_PRLIMIT;
1564*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1565*7c3d14c8STreehugger Robot MSAN_INTERCEPT_UNAME;
1566*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(gethostname);
1567*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1568*7c3d14c8STreehugger Robot MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1569*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(dladdr);
1570*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(dlerror);
1571*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(dl_iterate_phdr);
1572*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(getrusage);
1573*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(sigaction);
1574*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(signal);
1575*7c3d14c8STreehugger Robot #if defined(__mips__)
1576*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1577*7c3d14c8STreehugger Robot #else
1578*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(pthread_create);
1579*7c3d14c8STreehugger Robot #endif
1580*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(pthread_key_create);
1581*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(pthread_join);
1582*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(tzset);
1583*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(__cxa_atexit);
1584*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(shmat);
1585*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(fork);
1586*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(openpty);
1587*7c3d14c8STreehugger Robot INTERCEPT_FUNCTION(forkpty);
1588*7c3d14c8STreehugger Robot
1589*7c3d14c8STreehugger Robot inited = 1;
1590*7c3d14c8STreehugger Robot }
1591*7c3d14c8STreehugger Robot } // namespace __msan
1592