1 //===-- msan_interceptors.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of MemorySanitizer.
10 //
11 // Interceptors for standard library functions.
12 //
13 // FIXME: move as many interceptors as possible into
14 // sanitizer_common/sanitizer_common_interceptors.h
15 //===----------------------------------------------------------------------===//
16
17 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
18
19 #include "interception/interception.h"
20 #include "msan.h"
21 #include "msan_chained_origin_depot.h"
22 #include "msan_dl.h"
23 #include "msan_origin.h"
24 #include "msan_poisoning.h"
25 #include "msan_report.h"
26 #include "msan_thread.h"
27 #include "sanitizer_common/sanitizer_allocator.h"
28 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
29 #include "sanitizer_common/sanitizer_allocator_interface.h"
30 #include "sanitizer_common/sanitizer_atomic.h"
31 #include "sanitizer_common/sanitizer_common.h"
32 #include "sanitizer_common/sanitizer_errno.h"
33 #include "sanitizer_common/sanitizer_errno_codes.h"
34 #include "sanitizer_common/sanitizer_glibc_version.h"
35 #include "sanitizer_common/sanitizer_libc.h"
36 #include "sanitizer_common/sanitizer_linux.h"
37 #include "sanitizer_common/sanitizer_platform_interceptors.h"
38 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
39 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
40 #include "sanitizer_common/sanitizer_stackdepot.h"
41 #include "sanitizer_common/sanitizer_vector.h"
42
43 #if SANITIZER_NETBSD
44 #define fstat __fstat50
45 #define gettimeofday __gettimeofday50
46 #define getrusage __getrusage50
47 #define tzset __tzset50
48 #endif
49
50 #include <stdarg.h>
51 // ACHTUNG! No other system header includes in this file.
52 // Ideally, we should get rid of stdarg.h as well.
53
54 using namespace __msan;
55
56 using __sanitizer::memory_order;
57 using __sanitizer::atomic_load;
58 using __sanitizer::atomic_store;
59 using __sanitizer::atomic_uintptr_t;
60
61 DECLARE_REAL(SIZE_T, strlen, const char *s)
62 DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
63 DECLARE_REAL(void *, memcpy, void *dest, const void *src, SIZE_T n)
64 DECLARE_REAL(void *, memset, void *dest, int c, SIZE_T n)
65
66 // True if this is a nested interceptor.
67 static THREADLOCAL int in_interceptor_scope;
68
__msan_scoped_disable_interceptor_checks()69 void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope; }
__msan_scoped_enable_interceptor_checks()70 void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope; }
71
72 struct InterceptorScope {
InterceptorScopeInterceptorScope73 InterceptorScope() { ++in_interceptor_scope; }
~InterceptorScopeInterceptorScope74 ~InterceptorScope() { --in_interceptor_scope; }
75 };
76
IsInInterceptorScope()77 bool IsInInterceptorScope() {
78 return in_interceptor_scope;
79 }
80
81 struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc82 static bool UseImpl() { return !msan_inited; }
83 };
84
85 #define ENSURE_MSAN_INITED() do { \
86 CHECK(!msan_init_is_running); \
87 if (!msan_inited) { \
88 __msan_init(); \
89 } \
90 } while (0)
91
92 // Check that [x, x+n) range is unpoisoned.
93 #define CHECK_UNPOISONED_0(x, n) \
94 do { \
95 sptr __offset = __msan_test_shadow(x, n); \
96 if (__msan::IsInSymbolizerOrUnwider()) \
97 break; \
98 if (__offset >= 0 && __msan::flags()->report_umrs) { \
99 GET_CALLER_PC_BP; \
100 ReportUMRInsideAddressRange(__func__, x, n, __offset); \
101 __msan::PrintWarningWithOrigin( \
102 pc, bp, __msan_get_origin((const char *)x + __offset)); \
103 if (__msan::flags()->halt_on_error) { \
104 Printf("Exiting\n"); \
105 Die(); \
106 } \
107 } \
108 } while (0)
109
110 // Check that [x, x+n) range is unpoisoned unless we are in a nested
111 // interceptor.
112 #define CHECK_UNPOISONED(x, n) \
113 do { \
114 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
115 } while (0)
116
117 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
118 CHECK_UNPOISONED((x), \
119 common_flags()->strict_string_checks ? (len) + 1 : (n) )
120
121 #define CHECK_UNPOISONED_STRING(x, n) \
122 CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
123
124 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,fread_unlocked,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)125 INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
126 void *file) {
127 ENSURE_MSAN_INITED();
128 SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
129 if (res > 0)
130 __msan_unpoison(ptr, res *size);
131 return res;
132 }
133 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
134 #else
135 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
136 #endif
137
138 #if !SANITIZER_NETBSD
INTERCEPTOR(void *,mempcpy,void * dest,const void * src,SIZE_T n)139 INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
140 return (char *)__msan_memcpy(dest, src, n) + n;
141 }
142 #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
143 #else
144 #define MSAN_MAYBE_INTERCEPT_MEMPCPY
145 #endif
146
INTERCEPTOR(void *,memccpy,void * dest,const void * src,int c,SIZE_T n)147 INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
148 ENSURE_MSAN_INITED();
149 void *res = REAL(memccpy)(dest, src, c, n);
150 CHECK(!res || (res >= dest && res <= (char *)dest + n));
151 SIZE_T sz = res ? (char *)res - (char *)dest : n;
152 CHECK_UNPOISONED(src, sz);
153 __msan_unpoison(dest, sz);
154 return res;
155 }
156
INTERCEPTOR(void *,bcopy,const void * src,void * dest,SIZE_T n)157 INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
158 return __msan_memmove(dest, src, n);
159 }
160
INTERCEPTOR(int,posix_memalign,void ** memptr,SIZE_T alignment,SIZE_T size)161 INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
162 GET_MALLOC_STACK_TRACE;
163 CHECK_NE(memptr, 0);
164 int res = msan_posix_memalign(memptr, alignment, size, &stack);
165 if (!res)
166 __msan_unpoison(memptr, sizeof(*memptr));
167 return res;
168 }
169
170 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void *,memalign,SIZE_T alignment,SIZE_T size)171 INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {
172 GET_MALLOC_STACK_TRACE;
173 return msan_memalign(alignment, size, &stack);
174 }
175 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
176 #else
177 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
178 #endif
179
INTERCEPTOR(void *,aligned_alloc,SIZE_T alignment,SIZE_T size)180 INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
181 GET_MALLOC_STACK_TRACE;
182 return msan_aligned_alloc(alignment, size, &stack);
183 }
184
185 #if !SANITIZER_NETBSD
INTERCEPTOR(void *,__libc_memalign,SIZE_T alignment,SIZE_T size)186 INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {
187 GET_MALLOC_STACK_TRACE;
188 return msan_memalign(alignment, size, &stack);
189 }
190 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
191 #else
192 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
193 #endif
194
INTERCEPTOR(void *,valloc,SIZE_T size)195 INTERCEPTOR(void *, valloc, SIZE_T size) {
196 GET_MALLOC_STACK_TRACE;
197 return msan_valloc(size, &stack);
198 }
199
200 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void *,pvalloc,SIZE_T size)201 INTERCEPTOR(void *, pvalloc, SIZE_T size) {
202 GET_MALLOC_STACK_TRACE;
203 return msan_pvalloc(size, &stack);
204 }
205 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
206 #else
207 #define MSAN_MAYBE_INTERCEPT_PVALLOC
208 #endif
209
INTERCEPTOR(void,free,void * ptr)210 INTERCEPTOR(void, free, void *ptr) {
211 if (UNLIKELY(!ptr))
212 return;
213 if (DlsymAlloc::PointerIsMine(ptr))
214 return DlsymAlloc::Free(ptr);
215 GET_MALLOC_STACK_TRACE;
216 MsanDeallocate(&stack, ptr);
217 }
218
219 #if SANITIZER_INTERCEPT_FREE_SIZED
INTERCEPTOR(void,free_sized,void * ptr,uptr size)220 INTERCEPTOR(void, free_sized, void *ptr, uptr size) {
221 if (UNLIKELY(!ptr))
222 return;
223 if (DlsymAlloc::PointerIsMine(ptr))
224 return DlsymAlloc::Free(ptr);
225 GET_MALLOC_STACK_TRACE;
226 MsanDeallocate(&stack, ptr);
227 }
228 # define MSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
229 #else
230 # define MSAN_MAYBE_INTERCEPT_FREE_SIZED
231 #endif
232
233 #if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
INTERCEPTOR(void,free_aligned_sized,void * ptr,uptr alignment,uptr size)234 INTERCEPTOR(void, free_aligned_sized, void *ptr, uptr alignment, uptr size) {
235 if (UNLIKELY(!ptr))
236 return;
237 if (DlsymAlloc::PointerIsMine(ptr))
238 return DlsymAlloc::Free(ptr);
239 GET_MALLOC_STACK_TRACE;
240 MsanDeallocate(&stack, ptr);
241 }
242 # define MSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
243 INTERCEPT_FUNCTION(free_aligned_sized)
244 #else
245 # define MSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
246 #endif
247
248 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void,cfree,void * ptr)249 INTERCEPTOR(void, cfree, void *ptr) {
250 if (UNLIKELY(!ptr))
251 return;
252 if (DlsymAlloc::PointerIsMine(ptr))
253 return DlsymAlloc::Free(ptr);
254 GET_MALLOC_STACK_TRACE;
255 MsanDeallocate(&stack, ptr);
256 }
257 # define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
258 #else
259 #define MSAN_MAYBE_INTERCEPT_CFREE
260 #endif
261
262 #if !SANITIZER_NETBSD
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)263 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
264 return __sanitizer_get_allocated_size(ptr);
265 }
266 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
267 INTERCEPT_FUNCTION(malloc_usable_size)
268 #else
269 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
270 #endif
271
272 #if (!SANITIZER_FREEBSD && !SANITIZER_NETBSD) || __GLIBC_PREREQ(2, 33)
273 template <class T>
clear_mallinfo(T * sret)274 static NOINLINE void clear_mallinfo(T *sret) {
275 ENSURE_MSAN_INITED();
276 internal_memset(sret, 0, sizeof(*sret));
277 __msan_unpoison(sret, sizeof(*sret));
278 }
279 #endif
280
281 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
282 // Interceptors use NRVO and assume that sret will be pre-allocated in
283 // caller frame.
284 INTERCEPTOR(__sanitizer_struct_mallinfo, mallinfo,) {
285 __sanitizer_struct_mallinfo sret;
286 clear_mallinfo(&sret);
287 return sret;
288 }
289 # define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
290 #else
291 # define MSAN_MAYBE_INTERCEPT_MALLINFO
292 #endif
293
294 #if __GLIBC_PREREQ(2, 33)
INTERCEPTOR(__sanitizer_struct_mallinfo2,mallinfo2)295 INTERCEPTOR(__sanitizer_struct_mallinfo2, mallinfo2) {
296 __sanitizer_struct_mallinfo2 sret;
297 clear_mallinfo(&sret);
298 return sret;
299 }
300 # define MSAN_MAYBE_INTERCEPT_MALLINFO2 INTERCEPT_FUNCTION(mallinfo2)
301 #else
302 # define MSAN_MAYBE_INTERCEPT_MALLINFO2
303 #endif
304
305 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,mallopt,int cmd,int value)306 INTERCEPTOR(int, mallopt, int cmd, int value) {
307 return 0;
308 }
309 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
310 #else
311 #define MSAN_MAYBE_INTERCEPT_MALLOPT
312 #endif
313
314 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void,malloc_stats,void)315 INTERCEPTOR(void, malloc_stats, void) {
316 // FIXME: implement, but don't call REAL(malloc_stats)!
317 }
318 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
319 #else
320 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
321 #endif
322
INTERCEPTOR(char *,strcpy,char * dest,const char * src)323 INTERCEPTOR(char *, strcpy, char *dest, const char *src) {
324 ENSURE_MSAN_INITED();
325 GET_STORE_STACK_TRACE;
326 SIZE_T n = internal_strlen(src);
327 CHECK_UNPOISONED_STRING(src + n, 0);
328 char *res = REAL(strcpy)(dest, src);
329 CopyShadowAndOrigin(dest, src, n + 1, &stack);
330 return res;
331 }
332
INTERCEPTOR(char *,strncpy,char * dest,const char * src,SIZE_T n)333 INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {
334 ENSURE_MSAN_INITED();
335 GET_STORE_STACK_TRACE;
336 SIZE_T copy_size = internal_strnlen(src, n);
337 if (copy_size < n)
338 copy_size++; // trailing \0
339 char *res = REAL(strncpy)(dest, src, n);
340 CopyShadowAndOrigin(dest, src, copy_size, &stack);
341 __msan_unpoison(dest + copy_size, n - copy_size);
342 return res;
343 }
344
345 #if !SANITIZER_NETBSD
INTERCEPTOR(char *,stpcpy,char * dest,const char * src)346 INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {
347 ENSURE_MSAN_INITED();
348 GET_STORE_STACK_TRACE;
349 SIZE_T n = internal_strlen(src);
350 CHECK_UNPOISONED_STRING(src + n, 0);
351 char *res = REAL(stpcpy)(dest, src);
352 CopyShadowAndOrigin(dest, src, n + 1, &stack);
353 return res;
354 }
355
INTERCEPTOR(char *,stpncpy,char * dest,const char * src,SIZE_T n)356 INTERCEPTOR(char *, stpncpy, char *dest, const char *src, SIZE_T n) {
357 ENSURE_MSAN_INITED();
358 GET_STORE_STACK_TRACE;
359 SIZE_T copy_size = Min(n, internal_strnlen(src, n) + 1);
360 char *res = REAL(stpncpy)(dest, src, n);
361 CopyShadowAndOrigin(dest, src, copy_size, &stack);
362 __msan_unpoison(dest + copy_size, n - copy_size);
363 return res;
364 }
365 # define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
366 # define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
367 #else
368 #define MSAN_MAYBE_INTERCEPT_STPCPY
369 # define MSAN_MAYBE_INTERCEPT_STPNCPY
370 #endif
371
INTERCEPTOR(char *,strdup,char * src)372 INTERCEPTOR(char *, strdup, char *src) {
373 ENSURE_MSAN_INITED();
374 GET_STORE_STACK_TRACE;
375 // On FreeBSD strdup() leverages strlen().
376 InterceptorScope interceptor_scope;
377 SIZE_T n = internal_strlen(src);
378 CHECK_UNPOISONED_STRING(src + n, 0);
379 char *res = REAL(strdup)(src);
380 CopyShadowAndOrigin(res, src, n + 1, &stack);
381 return res;
382 }
383
384 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(char *,__strdup,char * src)385 INTERCEPTOR(char *, __strdup, char *src) {
386 ENSURE_MSAN_INITED();
387 GET_STORE_STACK_TRACE;
388 SIZE_T n = internal_strlen(src);
389 CHECK_UNPOISONED_STRING(src + n, 0);
390 char *res = REAL(__strdup)(src);
391 CopyShadowAndOrigin(res, src, n + 1, &stack);
392 return res;
393 }
394 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
395 #else
396 #define MSAN_MAYBE_INTERCEPT___STRDUP
397 #endif
398
399 #if !SANITIZER_NETBSD
INTERCEPTOR(char *,gcvt,double number,SIZE_T ndigit,char * buf)400 INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
401 ENSURE_MSAN_INITED();
402 char *res = REAL(gcvt)(number, ndigit, buf);
403 SIZE_T n = internal_strlen(buf);
404 __msan_unpoison(buf, n + 1);
405 return res;
406 }
407 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
408 #else
409 #define MSAN_MAYBE_INTERCEPT_GCVT
410 #endif
411
INTERCEPTOR(char *,strcat,char * dest,const char * src)412 INTERCEPTOR(char *, strcat, char *dest, const char *src) {
413 ENSURE_MSAN_INITED();
414 GET_STORE_STACK_TRACE;
415 SIZE_T src_size = internal_strlen(src);
416 SIZE_T dest_size = internal_strlen(dest);
417 CHECK_UNPOISONED_STRING(src + src_size, 0);
418 CHECK_UNPOISONED_STRING(dest + dest_size, 0);
419 char *res = REAL(strcat)(dest, src);
420 CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
421 return res;
422 }
423
INTERCEPTOR(char *,strncat,char * dest,const char * src,SIZE_T n)424 INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {
425 ENSURE_MSAN_INITED();
426 GET_STORE_STACK_TRACE;
427 SIZE_T dest_size = internal_strlen(dest);
428 SIZE_T copy_size = internal_strnlen(src, n);
429 CHECK_UNPOISONED_STRING(dest + dest_size, 0);
430 char *res = REAL(strncat)(dest, src, n);
431 CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
432 __msan_unpoison(dest + dest_size + copy_size, 1); // \0
433 return res;
434 }
435
436 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
437 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
438 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
439 ENSURE_MSAN_INITED(); \
440 ret_type res = REAL(func)(__VA_ARGS__); \
441 __msan_unpoison(endptr, sizeof(*endptr)); \
442 return res;
443
444 // On s390x, long double return values are passed via implicit reference,
445 // which needs to be unpoisoned. We make the implicit pointer explicit.
446 #define INTERCEPTOR_STRTO_SRET_BODY(func, sret, ...) \
447 ENSURE_MSAN_INITED(); \
448 REAL(func)(sret, __VA_ARGS__); \
449 __msan_unpoison(sret, sizeof(*sret)); \
450 __msan_unpoison(endptr, sizeof(*endptr));
451
452 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
453 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
454 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
455 }
456
457 #define INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
458 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
459 char_type **endptr) { \
460 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr); \
461 }
462
463 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
464 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
465 int base) { \
466 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
467 }
468
469 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
470 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
471 void *loc) { \
472 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
473 }
474
475 #define INTERCEPTOR_STRTO_SRET_LOC(ret_type, func, char_type) \
476 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
477 char_type **endptr, void *loc) { \
478 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr, loc); \
479 }
480
481 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
482 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
483 int base, void *loc) { \
484 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
485 }
486
487 #if SANITIZER_NETBSD
488 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
489 INTERCEPTOR_STRTO(ret_type, func, char_type) \
490 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
491
492 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
493 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
494 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type)
495
496 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
497 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
498 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
499
500 #else
501 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
502 INTERCEPTOR_STRTO(ret_type, func, char_type) \
503 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
504 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
505 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
506
507 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
508 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
509 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type) \
510 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_l, char_type) \
511 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_internal, char_type)
512
513 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
514 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
515 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
516 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
517 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
518 #endif
519
INTERCEPTORS_STRTO(double,strtod,char)520 INTERCEPTORS_STRTO(double, strtod, char)
521 INTERCEPTORS_STRTO(float, strtof, char)
522 #ifdef __s390x__
523 INTERCEPTORS_STRTO_SRET(long double, strtold, char)
524 #else
525 INTERCEPTORS_STRTO(long double, strtold, char)
526 #endif
527 INTERCEPTORS_STRTO_BASE(long, strtol, char)
528 INTERCEPTORS_STRTO_BASE(long long, strtoll, char)
529 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)
530 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)
531 INTERCEPTORS_STRTO_BASE(u64, strtouq, char)
532
533 INTERCEPTORS_STRTO(double, wcstod, wchar_t)
534 INTERCEPTORS_STRTO(float, wcstof, wchar_t)
535 #ifdef __s390x__
536 INTERCEPTORS_STRTO_SRET(long double, wcstold, wchar_t)
537 #else
538 INTERCEPTORS_STRTO(long double, wcstold, wchar_t)
539 #endif
540 INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)
541 INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
542 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
543 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)
544
545 #if SANITIZER_GLIBC
546 INTERCEPTORS_STRTO(double, __isoc23_strtod, char)
547 INTERCEPTORS_STRTO(float, __isoc23_strtof, char)
548 #ifdef __s390x__
549 INTERCEPTORS_STRTO_SRET(long double, __isoc23_strtold, char)
550 #else
551 INTERCEPTORS_STRTO(long double, __isoc23_strtold, char)
552 #endif
553 INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol, char)
554 INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll, char)
555 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul, char)
556 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull, char)
557 INTERCEPTORS_STRTO_BASE(u64, __isoc23_strtouq, char)
558
559 INTERCEPTORS_STRTO(double, __isoc23_wcstod, wchar_t)
560 INTERCEPTORS_STRTO(float, __isoc23_wcstof, wchar_t)
561 #ifdef __s390x__
562 INTERCEPTORS_STRTO_SRET(long double, __isoc23_wcstold, wchar_t)
563 #else
564 INTERCEPTORS_STRTO(long double, __isoc23_wcstold, wchar_t)
565 #endif
566 INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol, wchar_t)
567 INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll, wchar_t)
568 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul, wchar_t)
569 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull, wchar_t)
570 #endif
571
572 #if SANITIZER_NETBSD
573 #define INTERCEPT_STRTO(func) \
574 INTERCEPT_FUNCTION(func); \
575 INTERCEPT_FUNCTION(func##_l);
576 #else
577 #define INTERCEPT_STRTO(func) \
578 INTERCEPT_FUNCTION(func); \
579 INTERCEPT_FUNCTION(func##_l); \
580 INTERCEPT_FUNCTION(__##func##_l); \
581 INTERCEPT_FUNCTION(__##func##_internal);
582
583 #define INTERCEPT_STRTO_VER(func, ver) \
584 INTERCEPT_FUNCTION_VER(func, ver); \
585 INTERCEPT_FUNCTION_VER(func##_l, ver); \
586 INTERCEPT_FUNCTION_VER(__##func##_l, ver); \
587 INTERCEPT_FUNCTION_VER(__##func##_internal, ver);
588 #endif
589
590
591 // FIXME: support *wprintf in common format interceptors.
592 INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
593 ENSURE_MSAN_INITED();
594 int res = REAL(vswprintf)(str, size, format, ap);
595 if (res >= 0) {
596 __msan_unpoison(str, 4 * (res + 1));
597 }
598 return res;
599 }
600
INTERCEPTOR(int,swprintf,void * str,uptr size,void * format,...)601 INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
602 ENSURE_MSAN_INITED();
603 va_list ap;
604 va_start(ap, format);
605 int res = vswprintf(str, size, format, ap);
606 va_end(ap);
607 return res;
608 }
609
610 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
611 ENSURE_MSAN_INITED(); \
612 InterceptorScope interceptor_scope; \
613 ret_type res = REAL(func)(s, __VA_ARGS__); \
614 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
615 return res;
616
INTERCEPTOR(SIZE_T,strftime,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm)617 INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
618 __sanitizer_tm *tm) {
619 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
620 }
621
INTERCEPTOR(SIZE_T,strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)622 INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
623 __sanitizer_tm *tm, void *loc) {
624 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
625 }
626
627 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,__strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)628 INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
629 __sanitizer_tm *tm, void *loc) {
630 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
631 loc);
632 }
633 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
634 #else
635 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
636 #endif
637
INTERCEPTOR(SIZE_T,wcsftime,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm)638 INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
639 __sanitizer_tm *tm) {
640 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
641 }
642
INTERCEPTOR(SIZE_T,wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)643 INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
644 __sanitizer_tm *tm, void *loc) {
645 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
646 loc);
647 }
648
649 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,__wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)650 INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
651 __sanitizer_tm *tm, void *loc) {
652 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
653 loc);
654 }
655 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
656 #else
657 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
658 #endif
659
INTERCEPTOR(int,mbtowc,wchar_t * dest,const char * src,SIZE_T n)660 INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
661 ENSURE_MSAN_INITED();
662 int res = REAL(mbtowc)(dest, src, n);
663 if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
664 return res;
665 }
666
INTERCEPTOR(SIZE_T,mbrtowc,wchar_t * dest,const char * src,SIZE_T n,void * ps)667 INTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n,
668 void *ps) {
669 ENSURE_MSAN_INITED();
670 SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
671 if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
672 return res;
673 }
674
675 // 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)676 INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
677 ENSURE_MSAN_INITED();
678 GET_STORE_STACK_TRACE;
679 wchar_t *res = REAL(wmemcpy)(dest, src, n);
680 CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
681 return res;
682 }
683
684 #if !SANITIZER_NETBSD
INTERCEPTOR(wchar_t *,wmempcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)685 INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
686 ENSURE_MSAN_INITED();
687 GET_STORE_STACK_TRACE;
688 wchar_t *res = REAL(wmempcpy)(dest, src, n);
689 CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
690 return res;
691 }
692 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
693 #else
694 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
695 #endif
696
INTERCEPTOR(wchar_t *,wmemset,wchar_t * s,wchar_t c,SIZE_T n)697 INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
698 CHECK(MEM_IS_APP(s));
699 ENSURE_MSAN_INITED();
700 wchar_t *res = REAL(wmemset)(s, c, n);
701 __msan_unpoison(s, n * sizeof(wchar_t));
702 return res;
703 }
704
INTERCEPTOR(wchar_t *,wmemmove,wchar_t * dest,const wchar_t * src,SIZE_T n)705 INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
706 ENSURE_MSAN_INITED();
707 GET_STORE_STACK_TRACE;
708 wchar_t *res = REAL(wmemmove)(dest, src, n);
709 MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
710 return res;
711 }
712
INTERCEPTOR(int,wcscmp,const wchar_t * s1,const wchar_t * s2)713 INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
714 ENSURE_MSAN_INITED();
715 int res = REAL(wcscmp)(s1, s2);
716 return res;
717 }
718
INTERCEPTOR(int,gettimeofday,void * tv,void * tz)719 INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
720 ENSURE_MSAN_INITED();
721 int res = REAL(gettimeofday)(tv, tz);
722 if (tv)
723 __msan_unpoison(tv, 16);
724 if (tz)
725 __msan_unpoison(tz, 8);
726 return res;
727 }
728
729 #if !SANITIZER_NETBSD
INTERCEPTOR(char *,fcvt,double x,int a,int * b,int * c)730 INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
731 ENSURE_MSAN_INITED();
732 char *res = REAL(fcvt)(x, a, b, c);
733 __msan_unpoison(b, sizeof(*b));
734 __msan_unpoison(c, sizeof(*c));
735 if (res)
736 __msan_unpoison(res, internal_strlen(res) + 1);
737 return res;
738 }
739 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
740 #else
741 #define MSAN_MAYBE_INTERCEPT_FCVT
742 #endif
743
INTERCEPTOR(char *,getenv,char * name)744 INTERCEPTOR(char *, getenv, char *name) {
745 if (msan_init_is_running)
746 return REAL(getenv)(name);
747 ENSURE_MSAN_INITED();
748 char *res = REAL(getenv)(name);
749 if (res)
750 __msan_unpoison(res, internal_strlen(res) + 1);
751 return res;
752 }
753
754 extern char **environ;
755
UnpoisonEnviron()756 static void UnpoisonEnviron() {
757 char **envp = environ;
758 for (; *envp; ++envp) {
759 __msan_unpoison(envp, sizeof(*envp));
760 __msan_unpoison(*envp, internal_strlen(*envp) + 1);
761 }
762 // Trailing NULL pointer.
763 __msan_unpoison(envp, sizeof(*envp));
764 }
765
INTERCEPTOR(int,setenv,const char * name,const char * value,int overwrite)766 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
767 ENSURE_MSAN_INITED();
768 CHECK_UNPOISONED_STRING(name, 0);
769 int res = REAL(setenv)(name, value, overwrite);
770 if (!res) UnpoisonEnviron();
771 return res;
772 }
773
INTERCEPTOR(int,putenv,char * string)774 INTERCEPTOR(int, putenv, char *string) {
775 ENSURE_MSAN_INITED();
776 int res = REAL(putenv)(string);
777 if (!res) UnpoisonEnviron();
778 return res;
779 }
780
781 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
782 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat,int fd,void * buf)783 INTERCEPTOR(int, fstat, int fd, void *buf) {
784 ENSURE_MSAN_INITED();
785 int res = REAL(fstat)(fd, buf);
786 if (!res)
787 __msan_unpoison(buf, __sanitizer::struct_stat_sz);
788 return res;
789 }
790 # define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
791 #else
792 #define MSAN_MAYBE_INTERCEPT_FSTAT
793 #endif
794
795 #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat64,int fd,void * buf)796 INTERCEPTOR(int, fstat64, int fd, void *buf) {
797 ENSURE_MSAN_INITED();
798 int res = REAL(fstat64)(fd, buf);
799 if (!res)
800 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
801 return res;
802 }
803 # define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
804 #else
805 # define MSAN_MAYBE_INTERCEPT_FSTAT64
806 #endif
807
808 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat,int magic,int fd,void * buf)809 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
810 ENSURE_MSAN_INITED();
811 int res = REAL(__fxstat)(magic, fd, buf);
812 if (!res)
813 __msan_unpoison(buf, __sanitizer::struct_stat_sz);
814 return res;
815 }
816 # define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
817 #else
818 #define MSAN_MAYBE_INTERCEPT___FXSTAT
819 #endif
820
821 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat64,int magic,int fd,void * buf)822 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
823 ENSURE_MSAN_INITED();
824 int res = REAL(__fxstat64)(magic, fd, buf);
825 if (!res)
826 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
827 return res;
828 }
829 # define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
830 #else
831 # define MSAN_MAYBE_INTERCEPT___FXSTAT64
832 #endif
833
834 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat,int fd,char * pathname,void * buf,int flags)835 INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
836 ENSURE_MSAN_INITED();
837 int res = REAL(fstatat)(fd, pathname, buf, flags);
838 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
839 return res;
840 }
841 # define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
842 #else
843 # define MSAN_MAYBE_INTERCEPT_FSTATAT
844 #endif
845
846 #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat64,int fd,char * pathname,void * buf,int flags)847 INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) {
848 ENSURE_MSAN_INITED();
849 int res = REAL(fstatat64)(fd, pathname, buf, flags);
850 if (!res)
851 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
852 return res;
853 }
854 # define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
855 #else
856 # define MSAN_MAYBE_INTERCEPT_FSTATAT64
857 #endif
858
859 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat,int magic,int fd,char * pathname,void * buf,int flags)860 INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
861 int flags) {
862 ENSURE_MSAN_INITED();
863 int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
864 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
865 return res;
866 }
867 # define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
868 #else
869 # define MSAN_MAYBE_INTERCEPT___FXSTATAT
870 #endif
871
872 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat64,int magic,int fd,char * pathname,void * buf,int flags)873 INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
874 int flags) {
875 ENSURE_MSAN_INITED();
876 int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
877 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
878 return res;
879 }
880 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
881 #else
882 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64
883 #endif
884
INTERCEPTOR(int,pipe,int pipefd[2])885 INTERCEPTOR(int, pipe, int pipefd[2]) {
886 if (msan_init_is_running)
887 return REAL(pipe)(pipefd);
888 ENSURE_MSAN_INITED();
889 int res = REAL(pipe)(pipefd);
890 if (!res)
891 __msan_unpoison(pipefd, sizeof(int[2]));
892 return res;
893 }
894
INTERCEPTOR(int,pipe2,int pipefd[2],int flags)895 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
896 ENSURE_MSAN_INITED();
897 int res = REAL(pipe2)(pipefd, flags);
898 if (!res)
899 __msan_unpoison(pipefd, sizeof(int[2]));
900 return res;
901 }
902
INTERCEPTOR(int,socketpair,int domain,int type,int protocol,int sv[2])903 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
904 ENSURE_MSAN_INITED();
905 int res = REAL(socketpair)(domain, type, protocol, sv);
906 if (!res)
907 __msan_unpoison(sv, sizeof(int[2]));
908 return res;
909 }
910
911 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(char *,fgets_unlocked,char * s,int size,void * stream)912 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
913 ENSURE_MSAN_INITED();
914 char *res = REAL(fgets_unlocked)(s, size, stream);
915 if (res)
916 __msan_unpoison(s, internal_strlen(s) + 1);
917 return res;
918 }
919 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
920 #else
921 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
922 #endif
923
924 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
925 if (msan_init_is_running) \
926 return REAL(getrlimit)(resource, rlim); \
927 ENSURE_MSAN_INITED(); \
928 int res = REAL(func)(resource, rlim); \
929 if (!res) \
930 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
931 return res
932
INTERCEPTOR(int,getrlimit,int resource,void * rlim)933 INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
934 INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim);
935 }
936
937 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,__getrlimit,int resource,void * rlim)938 INTERCEPTOR(int, __getrlimit, int resource, void *rlim) {
939 INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim);
940 }
941
INTERCEPTOR(int,getrlimit64,int resource,void * rlim)942 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
943 if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
944 ENSURE_MSAN_INITED();
945 int res = REAL(getrlimit64)(resource, rlim);
946 if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
947 return res;
948 }
949
INTERCEPTOR(int,prlimit,int pid,int resource,void * new_rlimit,void * old_rlimit)950 INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
951 void *old_rlimit) {
952 if (msan_init_is_running)
953 return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
954 ENSURE_MSAN_INITED();
955 CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
956 int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
957 if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
958 return res;
959 }
960
INTERCEPTOR(int,prlimit64,int pid,int resource,void * new_rlimit,void * old_rlimit)961 INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
962 void *old_rlimit) {
963 if (msan_init_is_running)
964 return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
965 ENSURE_MSAN_INITED();
966 CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
967 int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
968 if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
969 return res;
970 }
971
972 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
973 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
974 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
975 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
976 #else
977 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
978 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
979 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
980 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
981 #endif
982
INTERCEPTOR(int,gethostname,char * name,SIZE_T len)983 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
984 ENSURE_MSAN_INITED();
985 int res = REAL(gethostname)(name, len);
986 if (!res || (res == -1 && errno == errno_ENAMETOOLONG)) {
987 SIZE_T real_len = internal_strnlen(name, len);
988 if (real_len < len)
989 ++real_len;
990 __msan_unpoison(name, real_len);
991 }
992 return res;
993 }
994
995 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)996 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
997 int timeout) {
998 ENSURE_MSAN_INITED();
999 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
1000 if (res > 0) {
1001 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
1002 }
1003 return res;
1004 }
1005 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
1006 #else
1007 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
1008 #endif
1009
1010 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_pwait,int epfd,void * events,int maxevents,int timeout,void * sigmask)1011 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
1012 int timeout, void *sigmask) {
1013 ENSURE_MSAN_INITED();
1014 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
1015 if (res > 0) {
1016 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
1017 }
1018 return res;
1019 }
1020 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
1021 #else
1022 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
1023 #endif
1024
INTERCEPTOR(void *,calloc,SIZE_T nmemb,SIZE_T size)1025 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
1026 GET_MALLOC_STACK_TRACE;
1027 if (DlsymAlloc::Use())
1028 return DlsymAlloc::Callocate(nmemb, size);
1029 return msan_calloc(nmemb, size, &stack);
1030 }
1031
INTERCEPTOR(void *,realloc,void * ptr,SIZE_T size)1032 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
1033 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
1034 return DlsymAlloc::Realloc(ptr, size);
1035 GET_MALLOC_STACK_TRACE;
1036 return msan_realloc(ptr, size, &stack);
1037 }
1038
INTERCEPTOR(void *,reallocarray,void * ptr,SIZE_T nmemb,SIZE_T size)1039 INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
1040 GET_MALLOC_STACK_TRACE;
1041 return msan_reallocarray(ptr, nmemb, size, &stack);
1042 }
1043
INTERCEPTOR(void *,malloc,SIZE_T size)1044 INTERCEPTOR(void *, malloc, SIZE_T size) {
1045 if (DlsymAlloc::Use())
1046 return DlsymAlloc::Allocate(size);
1047 GET_MALLOC_STACK_TRACE;
1048 return msan_malloc(size, &stack);
1049 }
1050
__msan_allocated_memory(const void * data,uptr size)1051 void __msan_allocated_memory(const void *data, uptr size) {
1052 if (flags()->poison_in_malloc) {
1053 GET_MALLOC_STACK_TRACE;
1054 stack.tag = STACK_TRACE_TAG_POISON;
1055 PoisonMemory(data, size, &stack);
1056 }
1057 }
1058
__msan_copy_shadow(void * dest,const void * src,uptr n)1059 void __msan_copy_shadow(void *dest, const void *src, uptr n) {
1060 GET_STORE_STACK_TRACE;
1061 MoveShadowAndOrigin(dest, src, n, &stack);
1062 }
1063
__sanitizer_dtor_callback(const void * data,uptr size)1064 void __sanitizer_dtor_callback(const void *data, uptr size) {
1065 if (flags()->poison_in_dtor) {
1066 GET_MALLOC_STACK_TRACE;
1067 stack.tag = STACK_TRACE_TAG_POISON;
1068 PoisonMemory(data, size, &stack);
1069 }
1070 }
1071
__sanitizer_dtor_callback_fields(const void * data,uptr size)1072 void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
1073 if (flags()->poison_in_dtor) {
1074 GET_MALLOC_STACK_TRACE;
1075 stack.tag = STACK_TRACE_TAG_FIELDS;
1076 PoisonMemory(data, size, &stack);
1077 }
1078 }
1079
__sanitizer_dtor_callback_vptr(const void * data)1080 void __sanitizer_dtor_callback_vptr(const void *data) {
1081 if (flags()->poison_in_dtor) {
1082 GET_MALLOC_STACK_TRACE;
1083 stack.tag = STACK_TRACE_TAG_VPTR;
1084 PoisonMemory(data, sizeof(void *), &stack);
1085 }
1086 }
1087
1088 template <class Mmap>
mmap_interceptor(Mmap real_mmap,void * addr,SIZE_T length,int prot,int flags,int fd,OFF64_T offset)1089 static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
1090 int prot, int flags, int fd, OFF64_T offset) {
1091 SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
1092 void *end_addr = (char *)addr + (rounded_length - 1);
1093 if (addr && (!MEM_IS_APP(addr) || !MEM_IS_APP(end_addr))) {
1094 if (flags & map_fixed) {
1095 errno = errno_EINVAL;
1096 return (void *)-1;
1097 } else {
1098 addr = nullptr;
1099 }
1100 }
1101 void *res = real_mmap(addr, length, prot, flags, fd, offset);
1102 if (res != (void *)-1) {
1103 void *end_res = (char *)res + (rounded_length - 1);
1104 if (MEM_IS_APP(res) && MEM_IS_APP(end_res)) {
1105 __msan_unpoison(res, rounded_length);
1106 } else {
1107 // Application has attempted to map more memory than is supported by
1108 // MSAN. Act as if we ran out of memory.
1109 internal_munmap(res, length);
1110 errno = errno_ENOMEM;
1111 return (void *)-1;
1112 }
1113 }
1114 return res;
1115 }
1116
INTERCEPTOR(int,getrusage,int who,void * usage)1117 INTERCEPTOR(int, getrusage, int who, void *usage) {
1118 ENSURE_MSAN_INITED();
1119 int res = REAL(getrusage)(who, usage);
1120 if (res == 0) {
1121 __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
1122 }
1123 return res;
1124 }
1125
1126 class SignalHandlerScope {
1127 public:
SignalHandlerScope()1128 SignalHandlerScope() {
1129 if (MsanThread *t = GetCurrentThread())
1130 t->EnterSignalHandler();
1131 }
~SignalHandlerScope()1132 ~SignalHandlerScope() {
1133 if (MsanThread *t = GetCurrentThread())
1134 t->LeaveSignalHandler();
1135 }
1136 };
1137
1138 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1139 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1140 // the signal handler.
1141 const int kMaxSignals = 1024;
1142 static atomic_uintptr_t sigactions[kMaxSignals];
1143 static StaticSpinMutex sigactions_mu;
1144
SignalHandler(int signo)1145 static void SignalHandler(int signo) {
1146 SignalHandlerScope signal_handler_scope;
1147 ScopedThreadLocalStateBackup stlsb;
1148 UnpoisonParam(1);
1149
1150 typedef void (*signal_cb)(int x);
1151 signal_cb cb =
1152 (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1153 cb(signo);
1154 }
1155
SignalAction(int signo,void * si,void * uc)1156 static void SignalAction(int signo, void *si, void *uc) {
1157 SignalHandlerScope signal_handler_scope;
1158 ScopedThreadLocalStateBackup stlsb;
1159 UnpoisonParam(3);
1160 __msan_unpoison(si, sizeof(__sanitizer_siginfo));
1161 __msan_unpoison(uc, ucontext_t_sz(uc));
1162
1163 typedef void (*sigaction_cb)(int, void *, void *);
1164 sigaction_cb cb =
1165 (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1166 cb(signo, si, uc);
1167 CHECK_UNPOISONED(uc, ucontext_t_sz(uc));
1168 }
1169
read_sigaction(const __sanitizer_sigaction * act)1170 static void read_sigaction(const __sanitizer_sigaction *act) {
1171 CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
1172 if (act->sa_flags & __sanitizer::sa_siginfo)
1173 CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
1174 else
1175 CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
1176 CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
1177 }
1178
1179 extern "C" int pthread_attr_init(void *attr);
1180 extern "C" int pthread_attr_destroy(void *attr);
1181
MsanThreadStartFunc(void * arg)1182 static void *MsanThreadStartFunc(void *arg) {
1183 MsanThread *t = (MsanThread *)arg;
1184 SetCurrentThread(t);
1185 t->Init();
1186 SetSigProcMask(&t->starting_sigset_, nullptr);
1187 return t->ThreadStart();
1188 }
1189
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)1190 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1191 void * param) {
1192 ENSURE_MSAN_INITED(); // for GetTlsSize()
1193 __sanitizer_pthread_attr_t myattr;
1194 if (!attr) {
1195 pthread_attr_init(&myattr);
1196 attr = &myattr;
1197 }
1198
1199 AdjustStackSize(attr);
1200
1201 MsanThread *t = MsanThread::Create(callback, param);
1202 ScopedBlockSignals block(&t->starting_sigset_);
1203 int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1204
1205 if (attr == &myattr)
1206 pthread_attr_destroy(&myattr);
1207 if (!res) {
1208 __msan_unpoison(th, __sanitizer::pthread_t_sz);
1209 }
1210 return res;
1211 }
1212
INTERCEPTOR(int,pthread_key_create,__sanitizer_pthread_key_t * key,void (* dtor)(void * value))1213 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1214 void (*dtor)(void *value)) {
1215 if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1216 ENSURE_MSAN_INITED();
1217 int res = REAL(pthread_key_create)(key, dtor);
1218 if (!res && key)
1219 __msan_unpoison(key, sizeof(*key));
1220 return res;
1221 }
1222
1223 #if SANITIZER_NETBSD
1224 INTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m,
1225 void (*dtor)(void *value))
1226 ALIAS(WRAP(pthread_key_create));
1227 #endif
1228
INTERCEPTOR(int,pthread_join,void * thread,void ** retval)1229 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
1230 ENSURE_MSAN_INITED();
1231 int res = REAL(pthread_join)(thread, retval);
1232 if (!res && retval)
1233 __msan_unpoison(retval, sizeof(*retval));
1234 return res;
1235 }
1236
1237 #if SANITIZER_GLIBC
INTERCEPTOR(int,pthread_tryjoin_np,void * thread,void ** retval)1238 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **retval) {
1239 ENSURE_MSAN_INITED();
1240 int res = REAL(pthread_tryjoin_np)(thread, retval);
1241 if (!res && retval)
1242 __msan_unpoison(retval, sizeof(*retval));
1243 return res;
1244 }
1245
INTERCEPTOR(int,pthread_timedjoin_np,void * thread,void ** retval,const struct timespec * abstime)1246 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **retval,
1247 const struct timespec *abstime) {
1248 int res = REAL(pthread_timedjoin_np)(thread, retval, abstime);
1249 if (!res && retval)
1250 __msan_unpoison(retval, sizeof(*retval));
1251 return res;
1252 }
1253 #endif
1254
1255 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
1256
1257 extern char *tzname[2];
1258
INTERCEPTOR(void,tzset,int fake)1259 INTERCEPTOR(void, tzset, int fake) {
1260 ENSURE_MSAN_INITED();
1261 InterceptorScope interceptor_scope;
1262 REAL(tzset)(fake);
1263 if (tzname[0])
1264 __msan_unpoison(tzname[0], internal_strlen(tzname[0]) + 1);
1265 if (tzname[1])
1266 __msan_unpoison(tzname[1], internal_strlen(tzname[1]) + 1);
1267 return;
1268 }
1269
1270 struct MSanAtExitRecord {
1271 void (*func)(void *arg);
1272 void *arg;
1273 };
1274
1275 struct InterceptorContext {
1276 Mutex atexit_mu;
1277 Vector<struct MSanAtExitRecord *> AtExitStack;
1278
InterceptorContextInterceptorContext1279 InterceptorContext()
1280 : AtExitStack() {
1281 }
1282 };
1283
1284 alignas(64) static char interceptor_placeholder[sizeof(InterceptorContext)];
interceptor_ctx()1285 InterceptorContext *interceptor_ctx() {
1286 return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
1287 }
1288
MSanAtExitWrapper()1289 void MSanAtExitWrapper() {
1290 MSanAtExitRecord *r;
1291 {
1292 Lock l(&interceptor_ctx()->atexit_mu);
1293
1294 uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
1295 r = interceptor_ctx()->AtExitStack[element];
1296 interceptor_ctx()->AtExitStack.PopBack();
1297 }
1298
1299 UnpoisonParam(1);
1300 ((void(*)())r->func)();
1301 InternalFree(r);
1302 }
1303
MSanCxaAtExitWrapper(void * arg)1304 void MSanCxaAtExitWrapper(void *arg) {
1305 UnpoisonParam(1);
1306 MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1307 // libc before 2.27 had race which caused occasional double handler execution
1308 // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1309 if (!r->func)
1310 return;
1311 r->func(r->arg);
1312 r->func = nullptr;
1313 }
1314
1315 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso);
1316
1317 // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)1318 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1319 void *dso_handle) {
1320 if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1321 return setup_at_exit_wrapper((void(*)())func, arg, dso_handle);
1322 }
1323
1324 // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,atexit,void (* func)())1325 INTERCEPTOR(int, atexit, void (*func)()) {
1326 // Avoid calling real atexit as it is unreachable on at least on Linux.
1327 if (msan_init_is_running)
1328 return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0);
1329 return setup_at_exit_wrapper((void(*)())func, 0, 0);
1330 }
1331
setup_at_exit_wrapper(void (* f)(),void * arg,void * dso)1332 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) {
1333 ENSURE_MSAN_INITED();
1334 MSanAtExitRecord *r =
1335 (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1336 r->func = (void(*)(void *a))f;
1337 r->arg = arg;
1338 int res;
1339 if (!dso) {
1340 // NetBSD does not preserve the 2nd argument if dso is equal to 0
1341 // Store ctx in a local stack-like structure
1342
1343 Lock l(&interceptor_ctx()->atexit_mu);
1344
1345 res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0);
1346 if (!res) {
1347 interceptor_ctx()->AtExitStack.PushBack(r);
1348 }
1349 } else {
1350 res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso);
1351 }
1352 return res;
1353 }
1354
1355 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1356 // with MSan.
1357 #if SANITIZER_LINUX
INTERCEPTOR(int,openpty,int * aparent,int * aworker,char * name,const void * termp,const void * winp)1358 INTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name,
1359 const void *termp, const void *winp) {
1360 ENSURE_MSAN_INITED();
1361 InterceptorScope interceptor_scope;
1362 int res = REAL(openpty)(aparent, aworker, name, termp, winp);
1363 if (!res) {
1364 __msan_unpoison(aparent, sizeof(*aparent));
1365 __msan_unpoison(aworker, sizeof(*aworker));
1366 }
1367 return res;
1368 }
1369 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1370 #else
1371 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1372 #endif
1373
1374 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1375 // with MSan.
1376 #if SANITIZER_LINUX
INTERCEPTOR(int,forkpty,int * aparent,char * name,const void * termp,const void * winp)1377 INTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp,
1378 const void *winp) {
1379 ENSURE_MSAN_INITED();
1380 InterceptorScope interceptor_scope;
1381 int res = REAL(forkpty)(aparent, name, termp, winp);
1382 if (res != -1)
1383 __msan_unpoison(aparent, sizeof(*aparent));
1384 return res;
1385 }
1386 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1387 #else
1388 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1389 #endif
1390
1391 struct MSanInterceptorContext {
1392 bool in_interceptor_scope;
1393 };
1394
1395 namespace __msan {
1396
OnExit()1397 int OnExit() {
1398 // FIXME: ask frontend whether we need to return failure.
1399 return 0;
1400 }
1401
1402 } // namespace __msan
1403
1404 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1405 // interceptors.
1406 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1407 do { \
1408 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1409 CHECK_UNPOISONED_0(x, n); \
1410 } while (0)
1411
1412 #define MSAN_INTERCEPT_FUNC(name) \
1413 do { \
1414 if (!INTERCEPT_FUNCTION(name)) \
1415 VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1416 } while (0)
1417
1418 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1419 do { \
1420 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
1421 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1422 ver); \
1423 } while (0)
1424 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
1425 do { \
1426 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
1427 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1428 #name, ver, #name); \
1429 } while (0)
1430
1431 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1432 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1433 MSAN_INTERCEPT_FUNC_VER(name, ver)
1434 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1435 MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1436 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1437 UnpoisonParam(count)
1438 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1439 __msan_unpoison(ptr, size)
1440 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1441 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1442 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1443 __msan_unpoison(ptr, size)
1444 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1445 if (msan_init_is_running) \
1446 return REAL(func)(__VA_ARGS__); \
1447 ENSURE_MSAN_INITED(); \
1448 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1449 ctx = (void *)&msan_ctx; \
1450 (void)ctx; \
1451 InterceptorScope interceptor_scope; \
1452 __msan_unpoison(__errno_location(), sizeof(int));
1453 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1454 do { \
1455 } while (false)
1456 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1457 do { \
1458 } while (false)
1459 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1460 do { \
1461 } while (false)
1462 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1463 do { \
1464 } while (false)
1465 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1466 do { \
1467 } while (false) // FIXME
1468 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1469 do { \
1470 } while (false) // FIXME
1471 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1472 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1473 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1474 do { \
1475 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1476 if (filename && map) \
1477 ForEachMappedRegion(map, __msan_unpoison); \
1478 } while (false)
1479
1480 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1481
1482 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1483 if (MsanThread *t = GetCurrentThread()) { \
1484 *begin = t->tls_begin(); \
1485 *end = t->tls_end(); \
1486 } else { \
1487 *begin = *end = 0; \
1488 }
1489
1490 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1491 { \
1492 (void)ctx; \
1493 return __msan_memset(block, c, size); \
1494 }
1495 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1496 { \
1497 (void)ctx; \
1498 return __msan_memmove(to, from, size); \
1499 }
1500 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1501 { \
1502 (void)ctx; \
1503 return __msan_memcpy(to, from, size); \
1504 }
1505
1506 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1507 do { \
1508 GET_STORE_STACK_TRACE; \
1509 CopyShadowAndOrigin(to, from, size, &stack); \
1510 __msan_unpoison(to + size, 1); \
1511 } while (false)
1512
1513 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1514 offset) \
1515 do { \
1516 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
1517 } while (false)
1518
1519 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1520 #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
1521 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1522
1523 static uptr signal_impl(int signo, uptr cb);
1524 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1525 __sanitizer_sigaction *oldact);
1526
1527 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1528 { return sigaction_impl(signo, act, oldact); }
1529
1530 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1531 { \
1532 handler = signal_impl(signo, handler); \
1533 InterceptorScope interceptor_scope; \
1534 return REAL(func)(signo, handler); \
1535 }
1536
1537 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
1538
1539 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1540
sigaction_impl(int signo,const __sanitizer_sigaction * act,__sanitizer_sigaction * oldact)1541 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1542 __sanitizer_sigaction *oldact) {
1543 ENSURE_MSAN_INITED();
1544 if (signo <= 0 || signo >= kMaxSignals) {
1545 errno = errno_EINVAL;
1546 return -1;
1547 }
1548 if (act) read_sigaction(act);
1549 int res;
1550 if (flags()->wrap_signals) {
1551 SpinMutexLock lock(&sigactions_mu);
1552 uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1553 __sanitizer_sigaction new_act;
1554 __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1555 if (act) {
1556 REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1557 uptr cb = (uptr)pnew_act->sigaction;
1558 uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1559 ? (uptr)SignalAction
1560 : (uptr)SignalHandler;
1561 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1562 atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1563 pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb;
1564 }
1565 }
1566 res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact);
1567 if (res == 0 && oldact) {
1568 uptr cb = (uptr)oldact->sigaction;
1569 if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) {
1570 oldact->sigaction = (decltype(oldact->sigaction))old_cb;
1571 }
1572 }
1573 } else {
1574 res = REAL(SIGACTION_SYMNAME)(signo, act, oldact);
1575 }
1576
1577 if (res == 0 && oldact) {
1578 __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1579 }
1580 return res;
1581 }
1582
signal_impl(int signo,uptr cb)1583 static uptr signal_impl(int signo, uptr cb) {
1584 ENSURE_MSAN_INITED();
1585 if (signo <= 0 || signo >= kMaxSignals) {
1586 errno = errno_EINVAL;
1587 return -1;
1588 }
1589 if (flags()->wrap_signals) {
1590 SpinMutexLock lock(&sigactions_mu);
1591 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1592 atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1593 cb = (uptr)&SignalHandler;
1594 }
1595 }
1596 return cb;
1597 }
1598
1599 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1600 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1601 do { \
1602 } while (false)
1603 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1604 do { \
1605 } while (false)
1606 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1607 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1608 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1609
INTERCEPTOR(const char *,strsignal,int sig)1610 INTERCEPTOR(const char *, strsignal, int sig) {
1611 void *ctx;
1612 COMMON_INTERCEPTOR_ENTER(ctx, strsignal, sig);
1613 const char *res = REAL(strsignal)(sig);
1614 if (res)
1615 __msan_unpoison(res, internal_strlen(res) + 1);
1616 return res;
1617 }
1618
INTERCEPTOR(int,dladdr,void * addr,void * info)1619 INTERCEPTOR(int, dladdr, void *addr, void *info) {
1620 void *ctx;
1621 COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1622 int res = REAL(dladdr)(addr, info);
1623 if (res != 0)
1624 UnpoisonDllAddrInfo(info);
1625 return res;
1626 }
1627
1628 #if SANITIZER_GLIBC
INTERCEPTOR(int,dladdr1,void * addr,void * info,void ** extra_info,int flags)1629 INTERCEPTOR(int, dladdr1, void *addr, void *info, void **extra_info,
1630 int flags) {
1631 void *ctx;
1632 COMMON_INTERCEPTOR_ENTER(ctx, dladdr1, addr, info, extra_info, flags);
1633 int res = REAL(dladdr1)(addr, info, extra_info, flags);
1634 if (res != 0) {
1635 UnpoisonDllAddrInfo(info);
1636 UnpoisonDllAddr1ExtraInfo(extra_info, flags);
1637 }
1638 return res;
1639 }
1640 # define MSAN_MAYBE_INTERCEPT_DLADDR1 MSAN_INTERCEPT_FUNC(dladdr1)
1641 #else
1642 #define MSAN_MAYBE_INTERCEPT_DLADDR1
1643 #endif
1644
INTERCEPTOR(char *,dlerror,int fake)1645 INTERCEPTOR(char *, dlerror, int fake) {
1646 void *ctx;
1647 COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1648 char *res = REAL(dlerror)(fake);
1649 if (res)
1650 __msan_unpoison(res, internal_strlen(res) + 1);
1651 return res;
1652 }
1653
1654 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1655 void *data);
1656 struct dl_iterate_phdr_data {
1657 dl_iterate_phdr_cb callback;
1658 void *data;
1659 };
1660
msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info * info,SIZE_T size,void * data)1661 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1662 void *data) {
1663 if (info) {
1664 __msan_unpoison(info, size);
1665 if (info->dlpi_phdr && info->dlpi_phnum)
1666 __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1667 if (info->dlpi_name)
1668 __msan_unpoison(info->dlpi_name, internal_strlen(info->dlpi_name) + 1);
1669 }
1670 dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1671 UnpoisonParam(3);
1672 return cbdata->callback(info, size, cbdata->data);
1673 }
1674
INTERCEPTOR(void *,shmat,int shmid,const void * shmaddr,int shmflg)1675 INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1676 ENSURE_MSAN_INITED();
1677 void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1678 if (p != (void *)-1) {
1679 __sanitizer_shmid_ds ds;
1680 int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1681 if (!res) {
1682 __msan_unpoison(p, ds.shm_segsz);
1683 }
1684 }
1685 return p;
1686 }
1687
INTERCEPTOR(int,dl_iterate_phdr,dl_iterate_phdr_cb callback,void * data)1688 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1689 void *ctx;
1690 COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1691 dl_iterate_phdr_data cbdata;
1692 cbdata.callback = callback;
1693 cbdata.data = data;
1694 int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1695 return res;
1696 }
1697
1698 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *,wcschr,void * s,wchar_t wc,void * ps)1699 INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
1700 ENSURE_MSAN_INITED();
1701 wchar_t *res = REAL(wcschr)(s, wc, ps);
1702 return res;
1703 }
1704
1705 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *,wcscpy,wchar_t * dest,const wchar_t * src)1706 INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
1707 ENSURE_MSAN_INITED();
1708 GET_STORE_STACK_TRACE;
1709 wchar_t *res = REAL(wcscpy)(dest, src);
1710 CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (internal_wcslen(src) + 1),
1711 &stack);
1712 return res;
1713 }
1714
INTERCEPTOR(wchar_t *,wcsncpy,wchar_t * dest,const wchar_t * src,SIZE_T n)1715 INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
1716 ENSURE_MSAN_INITED();
1717 GET_STORE_STACK_TRACE;
1718 SIZE_T copy_size = internal_wcsnlen(src, n);
1719 if (copy_size < n) copy_size++; // trailing \0
1720 wchar_t *res = REAL(wcsncpy)(dest, src, n);
1721 CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
1722 __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
1723 return res;
1724 }
1725
1726 // These interface functions reside here so that they can use
1727 // REAL(memset), etc.
__msan_unpoison(const void * a,uptr size)1728 void __msan_unpoison(const void *a, uptr size) {
1729 if (!MEM_IS_APP(a)) return;
1730 SetShadow(a, size, 0);
1731 }
1732
__msan_poison(const void * a,uptr size)1733 void __msan_poison(const void *a, uptr size) {
1734 if (!MEM_IS_APP(a)) return;
1735 SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1736 }
1737
__msan_poison_stack(void * a,uptr size)1738 void __msan_poison_stack(void *a, uptr size) {
1739 if (!MEM_IS_APP(a)) return;
1740 SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1741 }
1742
__msan_unpoison_param(uptr n)1743 void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }
1744
__msan_clear_and_unpoison(void * a,uptr size)1745 void __msan_clear_and_unpoison(void *a, uptr size) {
1746 REAL(memset)(a, 0, size);
1747 SetShadow(a, size, 0);
1748 }
1749
__msan_memcpy(void * dest,const void * src,SIZE_T n)1750 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1751 if (!msan_inited) return internal_memcpy(dest, src, n);
1752 if (msan_init_is_running || __msan::IsInSymbolizerOrUnwider())
1753 return REAL(memcpy)(dest, src, n);
1754 ENSURE_MSAN_INITED();
1755 GET_STORE_STACK_TRACE;
1756 void *res = REAL(memcpy)(dest, src, n);
1757 CopyShadowAndOrigin(dest, src, n, &stack);
1758 return res;
1759 }
1760
__msan_memset(void * s,int c,SIZE_T n)1761 void *__msan_memset(void *s, int c, SIZE_T n) {
1762 if (!msan_inited) return internal_memset(s, c, n);
1763 if (msan_init_is_running) return REAL(memset)(s, c, n);
1764 ENSURE_MSAN_INITED();
1765 void *res = REAL(memset)(s, c, n);
1766 __msan_unpoison(s, n);
1767 return res;
1768 }
1769
__msan_memmove(void * dest,const void * src,SIZE_T n)1770 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1771 if (!msan_inited) return internal_memmove(dest, src, n);
1772 if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1773 ENSURE_MSAN_INITED();
1774 GET_STORE_STACK_TRACE;
1775 void *res = REAL(memmove)(dest, src, n);
1776 MoveShadowAndOrigin(dest, src, n, &stack);
1777 return res;
1778 }
1779
__msan_unpoison_string(const char * s)1780 void __msan_unpoison_string(const char* s) {
1781 if (!MEM_IS_APP(s)) return;
1782 __msan_unpoison(s, internal_strlen(s) + 1);
1783 }
1784
1785 namespace __msan {
1786
InitializeInterceptors()1787 void InitializeInterceptors() {
1788 static int inited = 0;
1789 CHECK_EQ(inited, 0);
1790
1791 __interception::DoesNotSupportStaticLinking();
1792
1793 new(interceptor_ctx()) InterceptorContext();
1794
1795 InitializeCommonInterceptors();
1796 InitializeSignalInterceptors();
1797
1798 INTERCEPT_FUNCTION(posix_memalign);
1799 MSAN_MAYBE_INTERCEPT_MEMALIGN;
1800 MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
1801 INTERCEPT_FUNCTION(valloc);
1802 MSAN_MAYBE_INTERCEPT_PVALLOC;
1803 INTERCEPT_FUNCTION(malloc);
1804 INTERCEPT_FUNCTION(calloc);
1805 INTERCEPT_FUNCTION(realloc);
1806 INTERCEPT_FUNCTION(reallocarray);
1807 INTERCEPT_FUNCTION(free);
1808 MSAN_MAYBE_INTERCEPT_FREE_SIZED;
1809 MSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
1810 MSAN_MAYBE_INTERCEPT_CFREE;
1811 MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
1812 MSAN_MAYBE_INTERCEPT_MALLINFO;
1813 MSAN_MAYBE_INTERCEPT_MALLINFO2;
1814 MSAN_MAYBE_INTERCEPT_MALLOPT;
1815 MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1816 INTERCEPT_FUNCTION(fread);
1817 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1818 INTERCEPT_FUNCTION(memccpy);
1819 MSAN_MAYBE_INTERCEPT_MEMPCPY;
1820 INTERCEPT_FUNCTION(bcopy);
1821 INTERCEPT_FUNCTION(wmemset);
1822 INTERCEPT_FUNCTION(wmemcpy);
1823 MSAN_MAYBE_INTERCEPT_WMEMPCPY;
1824 INTERCEPT_FUNCTION(wmemmove);
1825 INTERCEPT_FUNCTION(strcpy);
1826 MSAN_MAYBE_INTERCEPT_STPCPY;
1827 MSAN_MAYBE_INTERCEPT_STPNCPY;
1828 INTERCEPT_FUNCTION(strdup);
1829 MSAN_MAYBE_INTERCEPT___STRDUP;
1830 INTERCEPT_FUNCTION(strncpy);
1831 MSAN_MAYBE_INTERCEPT_GCVT;
1832 INTERCEPT_FUNCTION(strcat);
1833 INTERCEPT_FUNCTION(strncat);
1834 INTERCEPT_STRTO(strtod);
1835 INTERCEPT_STRTO(strtof);
1836 #ifdef SANITIZER_NLDBL_VERSION
1837 INTERCEPT_STRTO_VER(strtold, SANITIZER_NLDBL_VERSION);
1838 #else
1839 INTERCEPT_STRTO(strtold);
1840 #endif
1841 INTERCEPT_STRTO(strtol);
1842 INTERCEPT_STRTO(strtoul);
1843 INTERCEPT_STRTO(strtoll);
1844 INTERCEPT_STRTO(strtoull);
1845 INTERCEPT_STRTO(strtouq);
1846 INTERCEPT_STRTO(wcstod);
1847 INTERCEPT_STRTO(wcstof);
1848 #ifdef SANITIZER_NLDBL_VERSION
1849 INTERCEPT_STRTO_VER(wcstold, SANITIZER_NLDBL_VERSION);
1850 #else
1851 INTERCEPT_STRTO(wcstold);
1852 #endif
1853 INTERCEPT_STRTO(wcstol);
1854 INTERCEPT_STRTO(wcstoul);
1855 INTERCEPT_STRTO(wcstoll);
1856 INTERCEPT_STRTO(wcstoull);
1857 #if SANITIZER_GLIBC
1858 INTERCEPT_STRTO(__isoc23_strtod);
1859 INTERCEPT_STRTO(__isoc23_strtof);
1860 INTERCEPT_STRTO(__isoc23_strtold);
1861 INTERCEPT_STRTO(__isoc23_strtol);
1862 INTERCEPT_STRTO(__isoc23_strtoul);
1863 INTERCEPT_STRTO(__isoc23_strtoll);
1864 INTERCEPT_STRTO(__isoc23_strtoull);
1865 INTERCEPT_STRTO(__isoc23_strtouq);
1866 INTERCEPT_STRTO(__isoc23_wcstod);
1867 INTERCEPT_STRTO(__isoc23_wcstof);
1868 INTERCEPT_STRTO(__isoc23_wcstold);
1869 INTERCEPT_STRTO(__isoc23_wcstol);
1870 INTERCEPT_STRTO(__isoc23_wcstoul);
1871 INTERCEPT_STRTO(__isoc23_wcstoll);
1872 INTERCEPT_STRTO(__isoc23_wcstoull);
1873 #endif
1874
1875 #ifdef SANITIZER_NLDBL_VERSION
1876 INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1877 INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1878 #else
1879 INTERCEPT_FUNCTION(vswprintf);
1880 INTERCEPT_FUNCTION(swprintf);
1881 #endif
1882 INTERCEPT_FUNCTION(strftime);
1883 INTERCEPT_FUNCTION(strftime_l);
1884 MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1885 INTERCEPT_FUNCTION(wcsftime);
1886 INTERCEPT_FUNCTION(wcsftime_l);
1887 MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1888 INTERCEPT_FUNCTION(mbtowc);
1889 INTERCEPT_FUNCTION(mbrtowc);
1890 INTERCEPT_FUNCTION(wcslen);
1891 INTERCEPT_FUNCTION(wcsnlen);
1892 INTERCEPT_FUNCTION(wcschr);
1893 INTERCEPT_FUNCTION(wcscpy);
1894 INTERCEPT_FUNCTION(wcsncpy);
1895 INTERCEPT_FUNCTION(wcscmp);
1896 INTERCEPT_FUNCTION(getenv);
1897 INTERCEPT_FUNCTION(setenv);
1898 INTERCEPT_FUNCTION(putenv);
1899 INTERCEPT_FUNCTION(gettimeofday);
1900 MSAN_MAYBE_INTERCEPT_FCVT;
1901 MSAN_MAYBE_INTERCEPT_FSTAT;
1902 MSAN_MAYBE_INTERCEPT_FSTAT64;
1903 MSAN_MAYBE_INTERCEPT___FXSTAT;
1904 MSAN_MAYBE_INTERCEPT_FSTATAT;
1905 MSAN_MAYBE_INTERCEPT_FSTATAT64;
1906 MSAN_MAYBE_INTERCEPT___FXSTATAT;
1907 MSAN_MAYBE_INTERCEPT___FXSTAT64;
1908 MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1909 INTERCEPT_FUNCTION(pipe);
1910 INTERCEPT_FUNCTION(pipe2);
1911 INTERCEPT_FUNCTION(socketpair);
1912 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1913 INTERCEPT_FUNCTION(getrlimit);
1914 MSAN_MAYBE_INTERCEPT___GETRLIMIT;
1915 MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1916 MSAN_MAYBE_INTERCEPT_PRLIMIT;
1917 MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1918 INTERCEPT_FUNCTION(gethostname);
1919 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1920 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1921 INTERCEPT_FUNCTION(strsignal);
1922 INTERCEPT_FUNCTION(dladdr);
1923 MSAN_MAYBE_INTERCEPT_DLADDR1;
1924 INTERCEPT_FUNCTION(dlerror);
1925 INTERCEPT_FUNCTION(dl_iterate_phdr);
1926 INTERCEPT_FUNCTION(getrusage);
1927 #if defined(__mips__)
1928 INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1929 #else
1930 INTERCEPT_FUNCTION(pthread_create);
1931 #endif
1932 INTERCEPT_FUNCTION(pthread_join);
1933 INTERCEPT_FUNCTION(pthread_key_create);
1934 #if SANITIZER_GLIBC
1935 INTERCEPT_FUNCTION(pthread_tryjoin_np);
1936 INTERCEPT_FUNCTION(pthread_timedjoin_np);
1937 #endif
1938
1939 #if SANITIZER_NETBSD
1940 INTERCEPT_FUNCTION(__libc_thr_keycreate);
1941 #endif
1942
1943 INTERCEPT_FUNCTION(pthread_join);
1944 INTERCEPT_FUNCTION(tzset);
1945 INTERCEPT_FUNCTION(atexit);
1946 INTERCEPT_FUNCTION(__cxa_atexit);
1947 INTERCEPT_FUNCTION(shmat);
1948 MSAN_MAYBE_INTERCEPT_OPENPTY;
1949 MSAN_MAYBE_INTERCEPT_FORKPTY;
1950
1951 inited = 1;
1952 }
1953 } // namespace __msan
1954