1 //===-- msan_interceptors.cc ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of MemorySanitizer.
12 // Interceptors for standard library functions.
14 // FIXME: move as many interceptors as possible into
15 // sanitizer_common/sanitizer_common_interceptors.h
16 //===----------------------------------------------------------------------===//
18 #include "interception/interception.h"
20 #include "msan_chained_origin_depot.h"
21 #include "msan_origin.h"
22 #include "msan_thread.h"
23 #include "msan_poisoning.h"
24 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
25 #include "sanitizer_common/sanitizer_allocator.h"
26 #include "sanitizer_common/sanitizer_allocator_interface.h"
27 #include "sanitizer_common/sanitizer_allocator_internal.h"
28 #include "sanitizer_common/sanitizer_atomic.h"
29 #include "sanitizer_common/sanitizer_common.h"
30 #include "sanitizer_common/sanitizer_stackdepot.h"
31 #include "sanitizer_common/sanitizer_libc.h"
32 #include "sanitizer_common/sanitizer_linux.h"
33 #include "sanitizer_common/sanitizer_tls_get_addr.h"
36 // ACHTUNG! No other system header includes in this file.
37 // Ideally, we should get rid of stdarg.h as well.
39 using namespace __msan
;
41 using __sanitizer::memory_order
;
42 using __sanitizer::atomic_load
;
43 using __sanitizer::atomic_store
;
44 using __sanitizer::atomic_uintptr_t
;
46 DECLARE_REAL(SIZE_T
, strlen
, const char *s
)
47 DECLARE_REAL(SIZE_T
, strnlen
, const char *s
, SIZE_T maxlen
)
50 #define __errno_location __error
53 // True if this is a nested interceptor.
54 static THREADLOCAL
int in_interceptor_scope
;
56 extern "C" int *__errno_location(void);
58 struct InterceptorScope
{
59 InterceptorScope() { ++in_interceptor_scope
; }
60 ~InterceptorScope() { --in_interceptor_scope
; }
63 bool IsInInterceptorScope() {
64 return in_interceptor_scope
;
67 #define ENSURE_MSAN_INITED() do { \
68 CHECK(!msan_init_is_running); \
74 // Check that [x, x+n) range is unpoisoned.
75 #define CHECK_UNPOISONED_0(x, n) \
77 sptr offset = __msan_test_shadow(x, n); \
78 if (__msan::IsInSymbolizer()) \
80 if (offset >= 0 && __msan::flags()->report_umrs) { \
81 GET_CALLER_PC_BP_SP; \
83 ReportUMRInsideAddressRange(__func__, x, n, offset); \
84 __msan::PrintWarningWithOrigin( \
85 pc, bp, __msan_get_origin((const char *)x + offset)); \
86 if (__msan::flags()->halt_on_error) { \
87 Printf("Exiting\n"); \
93 // Check that [x, x+n) range is unpoisoned unless we are in a nested
95 #define CHECK_UNPOISONED(x, n) \
97 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
100 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
101 CHECK_UNPOISONED((x), \
102 common_flags()->strict_string_checks ? (len) + 1 : (n) )
104 #define CHECK_UNPOISONED_STRING(x, n) \
105 CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
107 INTERCEPTOR(SIZE_T
, fread
, void *ptr
, SIZE_T size
, SIZE_T nmemb
, void *file
) {
108 ENSURE_MSAN_INITED();
109 SIZE_T res
= REAL(fread
)(ptr
, size
, nmemb
, file
);
111 __msan_unpoison(ptr
, res
*size
);
115 #if !SANITIZER_FREEBSD
116 INTERCEPTOR(SIZE_T
, fread_unlocked
, void *ptr
, SIZE_T size
, SIZE_T nmemb
,
118 ENSURE_MSAN_INITED();
119 SIZE_T res
= REAL(fread_unlocked
)(ptr
, size
, nmemb
, file
);
121 __msan_unpoison(ptr
, res
*size
);
124 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
126 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
129 INTERCEPTOR(SSIZE_T
, readlink
, const char *path
, char *buf
, SIZE_T bufsiz
) {
130 ENSURE_MSAN_INITED();
131 CHECK_UNPOISONED_STRING(path
, 0)
132 SSIZE_T res
= REAL(readlink
)(path
, buf
, bufsiz
);
134 __msan_unpoison(buf
, res
);
138 INTERCEPTOR(void *, memcpy
, void *dest
, const void *src
, SIZE_T n
) {
139 return __msan_memcpy(dest
, src
, n
);
142 INTERCEPTOR(void *, mempcpy
, void *dest
, const void *src
, SIZE_T n
) {
143 return (char *)__msan_memcpy(dest
, src
, n
) + n
;
146 INTERCEPTOR(void *, memccpy
, void *dest
, const void *src
, int c
, SIZE_T n
) {
147 ENSURE_MSAN_INITED();
148 void *res
= REAL(memccpy
)(dest
, src
, c
, n
);
149 CHECK(!res
|| (res
>= dest
&& res
<= (char *)dest
+ n
));
150 SIZE_T sz
= res
? (char *)res
- (char *)dest
: n
;
151 CHECK_UNPOISONED(src
, sz
);
152 __msan_unpoison(dest
, sz
);
156 INTERCEPTOR(void *, memmove
, void *dest
, const void *src
, SIZE_T n
) {
157 return __msan_memmove(dest
, src
, n
);
160 INTERCEPTOR(void *, memset
, void *s
, int c
, SIZE_T n
) {
161 return __msan_memset(s
, c
, n
);
164 INTERCEPTOR(void *, bcopy
, const void *src
, void *dest
, SIZE_T n
) {
165 return __msan_memmove(dest
, src
, n
);
168 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
169 GET_MALLOC_STACK_TRACE
;
170 CHECK_EQ(alignment
& (alignment
- 1), 0);
172 *memptr
= MsanReallocate(&stack
, nullptr, size
, alignment
, false);
173 CHECK_NE(*memptr
, 0);
174 __msan_unpoison(memptr
, sizeof(*memptr
));
178 #if !SANITIZER_FREEBSD
179 INTERCEPTOR(void *, memalign
, SIZE_T boundary
, SIZE_T size
) {
180 GET_MALLOC_STACK_TRACE
;
181 CHECK_EQ(boundary
& (boundary
- 1), 0);
182 void *ptr
= MsanReallocate(&stack
, nullptr, size
, boundary
, false);
185 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
187 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
190 INTERCEPTOR(void *, aligned_alloc
, SIZE_T boundary
, SIZE_T size
) {
191 GET_MALLOC_STACK_TRACE
;
192 CHECK_EQ(boundary
& (boundary
- 1), 0);
193 void *ptr
= MsanReallocate(&stack
, nullptr, size
, boundary
, false);
197 INTERCEPTOR(void *, __libc_memalign
, SIZE_T boundary
, SIZE_T size
) {
198 GET_MALLOC_STACK_TRACE
;
199 CHECK_EQ(boundary
& (boundary
- 1), 0);
200 void *ptr
= MsanReallocate(&stack
, nullptr, size
, boundary
, false);
201 DTLS_on_libc_memalign(ptr
, size
);
205 INTERCEPTOR(void *, valloc
, SIZE_T size
) {
206 GET_MALLOC_STACK_TRACE
;
207 void *ptr
= MsanReallocate(&stack
, nullptr, size
, GetPageSizeCached(), false);
211 #if !SANITIZER_FREEBSD
212 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
213 GET_MALLOC_STACK_TRACE
;
214 uptr PageSize
= GetPageSizeCached();
215 size
= RoundUpTo(size
, PageSize
);
217 // pvalloc(0) should allocate one page.
220 void *ptr
= MsanReallocate(&stack
, nullptr, size
, PageSize
, false);
223 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
225 #define MSAN_MAYBE_INTERCEPT_PVALLOC
228 INTERCEPTOR(void, free
, void *ptr
) {
229 GET_MALLOC_STACK_TRACE
;
231 MsanDeallocate(&stack
, ptr
);
234 #if !SANITIZER_FREEBSD
235 INTERCEPTOR(void, cfree
, void *ptr
) {
236 GET_MALLOC_STACK_TRACE
;
238 MsanDeallocate(&stack
, ptr
);
240 #define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
242 #define MSAN_MAYBE_INTERCEPT_CFREE
245 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
246 return __sanitizer_get_allocated_size(ptr
);
249 #if !SANITIZER_FREEBSD
250 // This function actually returns a struct by value, but we can't unpoison a
251 // temporary! The following is equivalent on all supported platforms but
252 // aarch64 (which uses a different register for sret value). We have a test
254 INTERCEPTOR(void, mallinfo
, __sanitizer_mallinfo
*sret
) {
257 asm volatile("mov %0,x8" : "=r" (r8
));
258 sret
= reinterpret_cast<__sanitizer_mallinfo
*>(r8
);
260 REAL(memset
)(sret
, 0, sizeof(*sret
));
261 __msan_unpoison(sret
, sizeof(*sret
));
263 #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
265 #define MSAN_MAYBE_INTERCEPT_MALLINFO
268 #if !SANITIZER_FREEBSD
269 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
272 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
274 #define MSAN_MAYBE_INTERCEPT_MALLOPT
277 #if !SANITIZER_FREEBSD
278 INTERCEPTOR(void, malloc_stats
, void) {
279 // FIXME: implement, but don't call REAL(malloc_stats)!
281 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
283 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
286 INTERCEPTOR(char *, strcpy
, char *dest
, const char *src
) { // NOLINT
287 ENSURE_MSAN_INITED();
288 GET_STORE_STACK_TRACE
;
289 SIZE_T n
= REAL(strlen
)(src
);
290 CHECK_UNPOISONED_STRING(src
+ n
, 0);
291 char *res
= REAL(strcpy
)(dest
, src
); // NOLINT
292 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
296 INTERCEPTOR(char *, strncpy
, char *dest
, const char *src
, SIZE_T n
) { // NOLINT
297 ENSURE_MSAN_INITED();
298 GET_STORE_STACK_TRACE
;
299 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
301 copy_size
++; // trailing \0
302 char *res
= REAL(strncpy
)(dest
, src
, n
); // NOLINT
303 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
304 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
308 INTERCEPTOR(char *, stpcpy
, char *dest
, const char *src
) { // NOLINT
309 ENSURE_MSAN_INITED();
310 GET_STORE_STACK_TRACE
;
311 SIZE_T n
= REAL(strlen
)(src
);
312 CHECK_UNPOISONED_STRING(src
+ n
, 0);
313 char *res
= REAL(stpcpy
)(dest
, src
); // NOLINT
314 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
318 INTERCEPTOR(char *, strdup
, char *src
) {
319 ENSURE_MSAN_INITED();
320 GET_STORE_STACK_TRACE
;
321 // On FreeBSD strdup() leverages strlen().
322 InterceptorScope interceptor_scope
;
323 SIZE_T n
= REAL(strlen
)(src
);
324 CHECK_UNPOISONED_STRING(src
+ n
, 0);
325 char *res
= REAL(strdup
)(src
);
326 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
330 #if !SANITIZER_FREEBSD
331 INTERCEPTOR(char *, __strdup
, char *src
) {
332 ENSURE_MSAN_INITED();
333 GET_STORE_STACK_TRACE
;
334 SIZE_T n
= REAL(strlen
)(src
);
335 CHECK_UNPOISONED_STRING(src
+ n
, 0);
336 char *res
= REAL(__strdup
)(src
);
337 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
340 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
342 #define MSAN_MAYBE_INTERCEPT___STRDUP
345 INTERCEPTOR(char *, strndup
, char *src
, SIZE_T n
) {
346 ENSURE_MSAN_INITED();
347 GET_STORE_STACK_TRACE
;
348 // On FreeBSD strndup() leverages strnlen().
349 InterceptorScope interceptor_scope
;
350 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
351 char *res
= REAL(strndup
)(src
, n
);
352 CopyShadowAndOrigin(res
, src
, copy_size
, &stack
);
353 __msan_unpoison(res
+ copy_size
, 1); // \0
357 #if !SANITIZER_FREEBSD
358 INTERCEPTOR(char *, __strndup
, char *src
, SIZE_T n
) {
359 ENSURE_MSAN_INITED();
360 GET_STORE_STACK_TRACE
;
361 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
362 char *res
= REAL(__strndup
)(src
, n
);
363 CopyShadowAndOrigin(res
, src
, copy_size
, &stack
);
364 __msan_unpoison(res
+ copy_size
, 1); // \0
367 #define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
369 #define MSAN_MAYBE_INTERCEPT___STRNDUP
372 INTERCEPTOR(char *, gcvt
, double number
, SIZE_T ndigit
, char *buf
) {
373 ENSURE_MSAN_INITED();
374 char *res
= REAL(gcvt
)(number
, ndigit
, buf
);
375 SIZE_T n
= REAL(strlen
)(buf
);
376 __msan_unpoison(buf
, n
+ 1);
380 INTERCEPTOR(char *, strcat
, char *dest
, const char *src
) { // NOLINT
381 ENSURE_MSAN_INITED();
382 GET_STORE_STACK_TRACE
;
383 SIZE_T src_size
= REAL(strlen
)(src
);
384 SIZE_T dest_size
= REAL(strlen
)(dest
);
385 CHECK_UNPOISONED_STRING(src
+ src_size
, 0);
386 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
387 char *res
= REAL(strcat
)(dest
, src
); // NOLINT
388 CopyShadowAndOrigin(dest
+ dest_size
, src
, src_size
+ 1, &stack
);
392 INTERCEPTOR(char *, strncat
, char *dest
, const char *src
, SIZE_T n
) { // NOLINT
393 ENSURE_MSAN_INITED();
394 GET_STORE_STACK_TRACE
;
395 SIZE_T dest_size
= REAL(strlen
)(dest
);
396 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
397 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
398 char *res
= REAL(strncat
)(dest
, src
, n
); // NOLINT
399 CopyShadowAndOrigin(dest
+ dest_size
, src
, copy_size
, &stack
);
400 __msan_unpoison(dest
+ dest_size
+ copy_size
, 1); // \0
404 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
405 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
406 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
407 ENSURE_MSAN_INITED(); \
408 ret_type res = REAL(func)(__VA_ARGS__); \
409 __msan_unpoison(endptr, sizeof(*endptr)); \
412 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
413 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
414 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
417 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
418 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
420 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
423 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
424 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
426 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
429 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
430 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
431 int base, void *loc) { \
432 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
435 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
436 INTERCEPTOR_STRTO(ret_type, func, char_type) \
437 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
438 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
439 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
441 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
442 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
443 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
444 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
445 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
447 INTERCEPTORS_STRTO(double, strtod
, char) // NOLINT
448 INTERCEPTORS_STRTO(float, strtof
, char) // NOLINT
449 INTERCEPTORS_STRTO(long double, strtold
, char) // NOLINT
450 INTERCEPTORS_STRTO_BASE(long, strtol
, char) // NOLINT
451 INTERCEPTORS_STRTO_BASE(long long, strtoll
, char) // NOLINT
452 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul
, char) // NOLINT
453 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull
, char) // NOLINT
455 INTERCEPTORS_STRTO(double, wcstod
, wchar_t) // NOLINT
456 INTERCEPTORS_STRTO(float, wcstof
, wchar_t) // NOLINT
457 INTERCEPTORS_STRTO(long double, wcstold
, wchar_t) // NOLINT
458 INTERCEPTORS_STRTO_BASE(long, wcstol
, wchar_t) // NOLINT
459 INTERCEPTORS_STRTO_BASE(long long, wcstoll
, wchar_t) // NOLINT
460 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul
, wchar_t) // NOLINT
461 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull
, wchar_t) // NOLINT
463 #define INTERCEPT_STRTO(func) \
464 INTERCEPT_FUNCTION(func); \
465 INTERCEPT_FUNCTION(func##_l); \
466 INTERCEPT_FUNCTION(__##func##_l); \
467 INTERCEPT_FUNCTION(__##func##_internal);
470 // FIXME: support *wprintf in common format interceptors.
471 INTERCEPTOR(int, vswprintf
, void *str
, uptr size
, void *format
, va_list ap
) {
472 ENSURE_MSAN_INITED();
473 int res
= REAL(vswprintf
)(str
, size
, format
, ap
);
475 __msan_unpoison(str
, 4 * (res
+ 1));
480 INTERCEPTOR(int, swprintf
, void *str
, uptr size
, void *format
, ...) {
481 ENSURE_MSAN_INITED();
483 va_start(ap
, format
);
484 int res
= vswprintf(str
, size
, format
, ap
);
489 INTERCEPTOR(SIZE_T
, strxfrm
, char *dest
, const char *src
, SIZE_T n
) {
490 ENSURE_MSAN_INITED();
491 CHECK_UNPOISONED(src
, REAL(strlen
)(src
) + 1);
492 SIZE_T res
= REAL(strxfrm
)(dest
, src
, n
);
493 if (res
< n
) __msan_unpoison(dest
, res
+ 1);
497 INTERCEPTOR(SIZE_T
, strxfrm_l
, char *dest
, const char *src
, SIZE_T n
,
499 ENSURE_MSAN_INITED();
500 CHECK_UNPOISONED(src
, REAL(strlen
)(src
) + 1);
501 SIZE_T res
= REAL(strxfrm_l
)(dest
, src
, n
, loc
);
502 if (res
< n
) __msan_unpoison(dest
, res
+ 1);
506 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
507 ENSURE_MSAN_INITED(); \
508 ret_type res = REAL(func)(s, __VA_ARGS__); \
509 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
512 INTERCEPTOR(SIZE_T
, strftime
, char *s
, SIZE_T max
, const char *format
,
513 __sanitizer_tm
*tm
) {
514 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime
, s
, max
, format
, tm
);
517 INTERCEPTOR(SIZE_T
, strftime_l
, char *s
, SIZE_T max
, const char *format
,
518 __sanitizer_tm
*tm
, void *loc
) {
519 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime_l
, s
, max
, format
, tm
, loc
);
522 #if !SANITIZER_FREEBSD
523 INTERCEPTOR(SIZE_T
, __strftime_l
, char *s
, SIZE_T max
, const char *format
,
524 __sanitizer_tm
*tm
, void *loc
) {
525 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, __strftime_l
, s
, max
, format
, tm
,
528 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
530 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
533 INTERCEPTOR(SIZE_T
, wcsftime
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
534 __sanitizer_tm
*tm
) {
535 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime
, s
, max
, format
, tm
);
538 INTERCEPTOR(SIZE_T
, wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
539 __sanitizer_tm
*tm
, void *loc
) {
540 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime_l
, s
, max
, format
, tm
,
544 #if !SANITIZER_FREEBSD
545 INTERCEPTOR(SIZE_T
, __wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
546 __sanitizer_tm
*tm
, void *loc
) {
547 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, __wcsftime_l
, s
, max
, format
, tm
,
550 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
552 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
555 INTERCEPTOR(int, mbtowc
, wchar_t *dest
, const char *src
, SIZE_T n
) {
556 ENSURE_MSAN_INITED();
557 int res
= REAL(mbtowc
)(dest
, src
, n
);
558 if (res
!= -1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
562 INTERCEPTOR(int, mbrtowc
, wchar_t *dest
, const char *src
, SIZE_T n
, void *ps
) {
563 ENSURE_MSAN_INITED();
564 SIZE_T res
= REAL(mbrtowc
)(dest
, src
, n
, ps
);
565 if (res
!= (SIZE_T
)-1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
569 INTERCEPTOR(SIZE_T
, wcslen
, const wchar_t *s
) {
570 ENSURE_MSAN_INITED();
571 SIZE_T res
= REAL(wcslen
)(s
);
572 CHECK_UNPOISONED(s
, sizeof(wchar_t) * (res
+ 1));
576 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
577 INTERCEPTOR(wchar_t *, wcschr
, void *s
, wchar_t wc
, void *ps
) {
578 ENSURE_MSAN_INITED();
579 wchar_t *res
= REAL(wcschr
)(s
, wc
, ps
);
583 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
584 INTERCEPTOR(wchar_t *, wcscpy
, wchar_t *dest
, const wchar_t *src
) {
585 ENSURE_MSAN_INITED();
586 GET_STORE_STACK_TRACE
;
587 wchar_t *res
= REAL(wcscpy
)(dest
, src
);
588 CopyShadowAndOrigin(dest
, src
, sizeof(wchar_t) * (REAL(wcslen
)(src
) + 1),
593 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
594 INTERCEPTOR(wchar_t *, wmemcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
595 ENSURE_MSAN_INITED();
596 GET_STORE_STACK_TRACE
;
597 wchar_t *res
= REAL(wmemcpy
)(dest
, src
, n
);
598 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
602 INTERCEPTOR(wchar_t *, wmempcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
603 ENSURE_MSAN_INITED();
604 GET_STORE_STACK_TRACE
;
605 wchar_t *res
= REAL(wmempcpy
)(dest
, src
, n
);
606 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
610 INTERCEPTOR(wchar_t *, wmemset
, wchar_t *s
, wchar_t c
, SIZE_T n
) {
611 CHECK(MEM_IS_APP(s
));
612 ENSURE_MSAN_INITED();
613 wchar_t *res
= REAL(wmemset
)(s
, c
, n
);
614 __msan_unpoison(s
, n
* sizeof(wchar_t));
618 INTERCEPTOR(wchar_t *, wmemmove
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
619 ENSURE_MSAN_INITED();
620 GET_STORE_STACK_TRACE
;
621 wchar_t *res
= REAL(wmemmove
)(dest
, src
, n
);
622 MoveShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
626 INTERCEPTOR(int, wcscmp
, const wchar_t *s1
, const wchar_t *s2
) {
627 ENSURE_MSAN_INITED();
628 int res
= REAL(wcscmp
)(s1
, s2
);
632 INTERCEPTOR(int, gettimeofday
, void *tv
, void *tz
) {
633 ENSURE_MSAN_INITED();
634 int res
= REAL(gettimeofday
)(tv
, tz
);
636 __msan_unpoison(tv
, 16);
638 __msan_unpoison(tz
, 8);
642 INTERCEPTOR(char *, fcvt
, double x
, int a
, int *b
, int *c
) {
643 ENSURE_MSAN_INITED();
644 char *res
= REAL(fcvt
)(x
, a
, b
, c
);
645 __msan_unpoison(b
, sizeof(*b
));
646 __msan_unpoison(c
, sizeof(*c
));
647 if (res
) __msan_unpoison(res
, REAL(strlen
)(res
) + 1);
651 INTERCEPTOR(char *, getenv
, char *name
) {
652 if (msan_init_is_running
)
653 return REAL(getenv
)(name
);
654 ENSURE_MSAN_INITED();
655 char *res
= REAL(getenv
)(name
);
656 if (res
) __msan_unpoison(res
, REAL(strlen
)(res
) + 1);
660 extern char **environ
;
662 static void UnpoisonEnviron() {
663 char **envp
= environ
;
664 for (; *envp
; ++envp
) {
665 __msan_unpoison(envp
, sizeof(*envp
));
666 __msan_unpoison(*envp
, REAL(strlen
)(*envp
) + 1);
668 // Trailing NULL pointer.
669 __msan_unpoison(envp
, sizeof(*envp
));
672 INTERCEPTOR(int, setenv
, const char *name
, const char *value
, int overwrite
) {
673 ENSURE_MSAN_INITED();
674 CHECK_UNPOISONED_STRING(name
, 0)
675 int res
= REAL(setenv
)(name
, value
, overwrite
);
676 if (!res
) UnpoisonEnviron();
680 INTERCEPTOR(int, putenv
, char *string
) {
681 ENSURE_MSAN_INITED();
682 int res
= REAL(putenv
)(string
);
683 if (!res
) UnpoisonEnviron();
687 #if !SANITIZER_FREEBSD
688 INTERCEPTOR(int, __fxstat
, int magic
, int fd
, void *buf
) {
689 ENSURE_MSAN_INITED();
690 int res
= REAL(__fxstat
)(magic
, fd
, buf
);
692 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
695 #define MSAN_MAYBE_INTERCEPT___FXSTAT INTERCEPT_FUNCTION(__fxstat)
697 #define MSAN_MAYBE_INTERCEPT___FXSTAT
700 #if !SANITIZER_FREEBSD
701 INTERCEPTOR(int, __fxstat64
, int magic
, int fd
, void *buf
) {
702 ENSURE_MSAN_INITED();
703 int res
= REAL(__fxstat64
)(magic
, fd
, buf
);
705 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
708 #define MSAN_MAYBE_INTERCEPT___FXSTAT64 INTERCEPT_FUNCTION(__fxstat64)
710 #define MSAN_MAYBE_INTERCEPT___FXSTAT64
713 #if SANITIZER_FREEBSD
714 INTERCEPTOR(int, fstatat
, int fd
, char *pathname
, void *buf
, int flags
) {
715 ENSURE_MSAN_INITED();
716 int res
= REAL(fstatat
)(fd
, pathname
, buf
, flags
);
717 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
720 # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat)
722 INTERCEPTOR(int, __fxstatat
, int magic
, int fd
, char *pathname
, void *buf
,
724 ENSURE_MSAN_INITED();
725 int res
= REAL(__fxstatat
)(magic
, fd
, pathname
, buf
, flags
);
726 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
729 # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat)
732 #if !SANITIZER_FREEBSD
733 INTERCEPTOR(int, __fxstatat64
, int magic
, int fd
, char *pathname
, void *buf
,
735 ENSURE_MSAN_INITED();
736 int res
= REAL(__fxstatat64
)(magic
, fd
, pathname
, buf
, flags
);
737 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
740 #define MSAN_MAYBE_INTERCEPT___FXSTATAT64 INTERCEPT_FUNCTION(__fxstatat64)
742 #define MSAN_MAYBE_INTERCEPT___FXSTATAT64
745 INTERCEPTOR(int, pipe
, int pipefd
[2]) {
746 if (msan_init_is_running
)
747 return REAL(pipe
)(pipefd
);
748 ENSURE_MSAN_INITED();
749 int res
= REAL(pipe
)(pipefd
);
751 __msan_unpoison(pipefd
, sizeof(int[2]));
755 INTERCEPTOR(int, pipe2
, int pipefd
[2], int flags
) {
756 ENSURE_MSAN_INITED();
757 int res
= REAL(pipe2
)(pipefd
, flags
);
759 __msan_unpoison(pipefd
, sizeof(int[2]));
763 INTERCEPTOR(int, socketpair
, int domain
, int type
, int protocol
, int sv
[2]) {
764 ENSURE_MSAN_INITED();
765 int res
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
767 __msan_unpoison(sv
, sizeof(int[2]));
771 INTERCEPTOR(char *, fgets
, char *s
, int size
, void *stream
) {
772 ENSURE_MSAN_INITED();
773 char *res
= REAL(fgets
)(s
, size
, stream
);
775 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
779 #if !SANITIZER_FREEBSD
780 INTERCEPTOR(char *, fgets_unlocked
, char *s
, int size
, void *stream
) {
781 ENSURE_MSAN_INITED();
782 char *res
= REAL(fgets_unlocked
)(s
, size
, stream
);
784 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
787 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
789 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
792 INTERCEPTOR(int, getrlimit
, int resource
, void *rlim
) {
793 if (msan_init_is_running
)
794 return REAL(getrlimit
)(resource
, rlim
);
795 ENSURE_MSAN_INITED();
796 int res
= REAL(getrlimit
)(resource
, rlim
);
798 __msan_unpoison(rlim
, __sanitizer::struct_rlimit_sz
);
802 #if !SANITIZER_FREEBSD
803 INTERCEPTOR(int, getrlimit64
, int resource
, void *rlim
) {
804 if (msan_init_is_running
) return REAL(getrlimit64
)(resource
, rlim
);
805 ENSURE_MSAN_INITED();
806 int res
= REAL(getrlimit64
)(resource
, rlim
);
807 if (!res
) __msan_unpoison(rlim
, __sanitizer::struct_rlimit64_sz
);
811 INTERCEPTOR(int, prlimit
, int pid
, int resource
, void *new_rlimit
,
813 if (msan_init_is_running
)
814 return REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
815 ENSURE_MSAN_INITED();
816 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit_sz
);
817 int res
= REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
818 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit_sz
);
822 INTERCEPTOR(int, prlimit64
, int pid
, int resource
, void *new_rlimit
,
824 if (msan_init_is_running
)
825 return REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
826 ENSURE_MSAN_INITED();
827 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit64_sz
);
828 int res
= REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
829 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit64_sz
);
833 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
834 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
835 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
837 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
838 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
839 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
842 #if SANITIZER_FREEBSD
843 // FreeBSD's <sys/utsname.h> define uname() as
844 // static __inline int uname(struct utsname *name) {
845 // return __xuname(SYS_NMLN, (void*)name);
847 INTERCEPTOR(int, __xuname
, int size
, void *utsname
) {
848 ENSURE_MSAN_INITED();
849 int res
= REAL(__xuname
)(size
, utsname
);
851 __msan_unpoison(utsname
, __sanitizer::struct_utsname_sz
);
854 #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname)
856 INTERCEPTOR(int, uname
, struct utsname
*utsname
) {
857 ENSURE_MSAN_INITED();
858 int res
= REAL(uname
)(utsname
);
860 __msan_unpoison(utsname
, __sanitizer::struct_utsname_sz
);
863 #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname)
866 INTERCEPTOR(int, gethostname
, char *name
, SIZE_T len
) {
867 ENSURE_MSAN_INITED();
868 int res
= REAL(gethostname
)(name
, len
);
870 SIZE_T real_len
= REAL(strnlen
)(name
, len
);
873 __msan_unpoison(name
, real_len
);
878 #if !SANITIZER_FREEBSD
879 INTERCEPTOR(int, epoll_wait
, int epfd
, void *events
, int maxevents
,
881 ENSURE_MSAN_INITED();
882 int res
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
884 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
888 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
890 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
893 #if !SANITIZER_FREEBSD
894 INTERCEPTOR(int, epoll_pwait
, int epfd
, void *events
, int maxevents
,
895 int timeout
, void *sigmask
) {
896 ENSURE_MSAN_INITED();
897 int res
= REAL(epoll_pwait
)(epfd
, events
, maxevents
, timeout
, sigmask
);
899 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
903 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
905 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
908 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
909 GET_MALLOC_STACK_TRACE
;
910 if (UNLIKELY(!msan_inited
)) {
911 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
912 const SIZE_T kCallocPoolSize
= 1024;
913 static uptr calloc_memory_for_dlsym
[kCallocPoolSize
];
914 static SIZE_T allocated
;
915 SIZE_T size_in_words
= ((nmemb
* size
) + kWordSize
- 1) / kWordSize
;
916 void *mem
= (void*)&calloc_memory_for_dlsym
[allocated
];
917 allocated
+= size_in_words
;
918 CHECK(allocated
< kCallocPoolSize
);
921 return MsanCalloc(&stack
, nmemb
, size
);
924 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
925 GET_MALLOC_STACK_TRACE
;
926 return MsanReallocate(&stack
, ptr
, size
, sizeof(u64
), false);
929 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
930 GET_MALLOC_STACK_TRACE
;
931 return MsanReallocate(&stack
, nullptr, size
, sizeof(u64
), false);
934 void __msan_allocated_memory(const void *data
, uptr size
) {
935 GET_MALLOC_STACK_TRACE
;
936 if (flags()->poison_in_malloc
) {
937 stack
.tag
= STACK_TRACE_TAG_POISON
;
938 PoisonMemory(data
, size
, &stack
);
942 void __msan_copy_shadow(void *dest
, const void *src
, uptr n
) {
943 GET_STORE_STACK_TRACE
;
944 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
947 void __sanitizer_dtor_callback(const void *data
, uptr size
) {
948 GET_MALLOC_STACK_TRACE
;
949 if (flags()->poison_in_dtor
) {
950 stack
.tag
= STACK_TRACE_TAG_POISON
;
951 PoisonMemory(data
, size
, &stack
);
955 INTERCEPTOR(void *, mmap
, void *addr
, SIZE_T length
, int prot
, int flags
,
956 int fd
, OFF_T offset
) {
957 if (msan_init_is_running
)
958 return REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
959 ENSURE_MSAN_INITED();
960 if (addr
&& !MEM_IS_APP(addr
)) {
961 if (flags
& map_fixed
) {
962 *__errno_location() = errno_EINVAL
;
968 void *res
= REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
969 if (res
!= (void*)-1)
970 __msan_unpoison(res
, RoundUpTo(length
, GetPageSize()));
974 #if !SANITIZER_FREEBSD
975 INTERCEPTOR(void *, mmap64
, void *addr
, SIZE_T length
, int prot
, int flags
,
976 int fd
, OFF64_T offset
) {
977 ENSURE_MSAN_INITED();
978 if (addr
&& !MEM_IS_APP(addr
)) {
979 if (flags
& map_fixed
) {
980 *__errno_location() = errno_EINVAL
;
986 void *res
= REAL(mmap64
)(addr
, length
, prot
, flags
, fd
, offset
);
987 if (res
!= (void*)-1)
988 __msan_unpoison(res
, RoundUpTo(length
, GetPageSize()));
991 #define MSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
993 #define MSAN_MAYBE_INTERCEPT_MMAP64
996 INTERCEPTOR(int, getrusage
, int who
, void *usage
) {
997 ENSURE_MSAN_INITED();
998 int res
= REAL(getrusage
)(who
, usage
);
1000 __msan_unpoison(usage
, __sanitizer::struct_rusage_sz
);
1005 class SignalHandlerScope
{
1007 SignalHandlerScope() {
1008 if (MsanThread
*t
= GetCurrentThread())
1009 t
->EnterSignalHandler();
1011 ~SignalHandlerScope() {
1012 if (MsanThread
*t
= GetCurrentThread())
1013 t
->LeaveSignalHandler();
1017 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1018 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1019 // the signal handler.
1020 const int kMaxSignals
= 1024;
1021 static atomic_uintptr_t sigactions
[kMaxSignals
];
1022 static StaticSpinMutex sigactions_mu
;
1024 static void SignalHandler(int signo
) {
1025 SignalHandlerScope signal_handler_scope
;
1026 ScopedThreadLocalStateBackup stlsb
;
1029 typedef void (*signal_cb
)(int x
);
1031 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1035 static void SignalAction(int signo
, void *si
, void *uc
) {
1036 SignalHandlerScope signal_handler_scope
;
1037 ScopedThreadLocalStateBackup stlsb
;
1039 __msan_unpoison(si
, sizeof(__sanitizer_sigaction
));
1040 __msan_unpoison(uc
, __sanitizer::ucontext_t_sz
);
1042 typedef void (*sigaction_cb
)(int, void *, void *);
1044 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1048 INTERCEPTOR(int, sigaction
, int signo
, const __sanitizer_sigaction
*act
,
1049 __sanitizer_sigaction
*oldact
) {
1050 ENSURE_MSAN_INITED();
1051 // FIXME: check that *act is unpoisoned.
1052 // That requires intercepting all of sigemptyset, sigfillset, etc.
1054 if (flags()->wrap_signals
) {
1055 SpinMutexLock
lock(&sigactions_mu
);
1056 CHECK_LT(signo
, kMaxSignals
);
1057 uptr old_cb
= atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1058 __sanitizer_sigaction new_act
;
1059 __sanitizer_sigaction
*pnew_act
= act
? &new_act
: nullptr;
1061 REAL(memcpy
)(pnew_act
, act
, sizeof(__sanitizer_sigaction
));
1062 uptr cb
= (uptr
)pnew_act
->sigaction
;
1063 uptr new_cb
= (pnew_act
->sa_flags
& __sanitizer::sa_siginfo
)
1064 ? (uptr
)SignalAction
1065 : (uptr
)SignalHandler
;
1066 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1067 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1068 pnew_act
->sigaction
= (void (*)(int, void *, void *))new_cb
;
1071 res
= REAL(sigaction
)(signo
, pnew_act
, oldact
);
1072 if (res
== 0 && oldact
) {
1073 uptr cb
= (uptr
)oldact
->sigaction
;
1074 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1075 oldact
->sigaction
= (void (*)(int, void *, void *))old_cb
;
1079 res
= REAL(sigaction
)(signo
, act
, oldact
);
1082 if (res
== 0 && oldact
) {
1083 __msan_unpoison(oldact
, sizeof(__sanitizer_sigaction
));
1088 INTERCEPTOR(int, signal
, int signo
, uptr cb
) {
1089 ENSURE_MSAN_INITED();
1090 if (flags()->wrap_signals
) {
1091 CHECK_LT(signo
, kMaxSignals
);
1092 SpinMutexLock
lock(&sigactions_mu
);
1093 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1094 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1095 cb
= (uptr
) SignalHandler
;
1097 return REAL(signal
)(signo
, cb
);
1099 return REAL(signal
)(signo
, cb
);
1103 extern "C" int pthread_attr_init(void *attr
);
1104 extern "C" int pthread_attr_destroy(void *attr
);
1106 static void *MsanThreadStartFunc(void *arg
) {
1107 MsanThread
*t
= (MsanThread
*)arg
;
1108 SetCurrentThread(t
);
1109 return t
->ThreadStart();
1112 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
, void *(*callback
)(void*),
1114 ENSURE_MSAN_INITED(); // for GetTlsSize()
1115 __sanitizer_pthread_attr_t myattr
;
1117 pthread_attr_init(&myattr
);
1121 AdjustStackSize(attr
);
1123 MsanThread
*t
= MsanThread::Create(callback
, param
);
1125 int res
= REAL(pthread_create
)(th
, attr
, MsanThreadStartFunc
, t
);
1127 if (attr
== &myattr
)
1128 pthread_attr_destroy(&myattr
);
1130 __msan_unpoison(th
, __sanitizer::pthread_t_sz
);
1135 INTERCEPTOR(int, pthread_key_create
, __sanitizer_pthread_key_t
*key
,
1136 void (*dtor
)(void *value
)) {
1137 if (msan_init_is_running
) return REAL(pthread_key_create
)(key
, dtor
);
1138 ENSURE_MSAN_INITED();
1139 int res
= REAL(pthread_key_create
)(key
, dtor
);
1141 __msan_unpoison(key
, sizeof(*key
));
1145 INTERCEPTOR(int, pthread_join
, void *th
, void **retval
) {
1146 ENSURE_MSAN_INITED();
1147 int res
= REAL(pthread_join
)(th
, retval
);
1149 __msan_unpoison(retval
, sizeof(*retval
));
1153 extern char *tzname
[2];
1155 INTERCEPTOR(void, tzset
, int fake
) {
1156 ENSURE_MSAN_INITED();
1159 __msan_unpoison(tzname
[0], REAL(strlen
)(tzname
[0]) + 1);
1161 __msan_unpoison(tzname
[1], REAL(strlen
)(tzname
[1]) + 1);
1165 struct MSanAtExitRecord
{
1166 void (*func
)(void *arg
);
1170 void MSanAtExitWrapper(void *arg
) {
1172 MSanAtExitRecord
*r
= (MSanAtExitRecord
*)arg
;
1177 // Unpoison argument shadow for C++ module destructors.
1178 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
1180 if (msan_init_is_running
) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
1181 ENSURE_MSAN_INITED();
1182 MSanAtExitRecord
*r
=
1183 (MSanAtExitRecord
*)InternalAlloc(sizeof(MSanAtExitRecord
));
1186 return REAL(__cxa_atexit
)(MSanAtExitWrapper
, r
, dso_handle
);
1189 DECLARE_REAL(int, shmctl
, int shmid
, int cmd
, void *buf
)
1191 INTERCEPTOR(void *, shmat
, int shmid
, const void *shmaddr
, int shmflg
) {
1192 ENSURE_MSAN_INITED();
1193 void *p
= REAL(shmat
)(shmid
, shmaddr
, shmflg
);
1194 if (p
!= (void *)-1) {
1195 __sanitizer_shmid_ds ds
;
1196 int res
= REAL(shmctl
)(shmid
, shmctl_ipc_stat
, &ds
);
1198 __msan_unpoison(p
, ds
.shm_segsz
);
1204 static void BeforeFork() {
1205 StackDepotLockAll();
1206 ChainedOriginDepotLockAll();
1209 static void AfterFork() {
1210 ChainedOriginDepotUnlockAll();
1211 StackDepotUnlockAll();
1214 INTERCEPTOR(int, fork
, void) {
1215 ENSURE_MSAN_INITED();
1217 int pid
= REAL(fork
)();
1222 INTERCEPTOR(int, openpty
, int *amaster
, int *aslave
, char *name
,
1223 const void *termp
, const void *winp
) {
1224 ENSURE_MSAN_INITED();
1225 InterceptorScope interceptor_scope
;
1226 int res
= REAL(openpty
)(amaster
, aslave
, name
, termp
, winp
);
1228 __msan_unpoison(amaster
, sizeof(*amaster
));
1229 __msan_unpoison(aslave
, sizeof(*aslave
));
1234 INTERCEPTOR(int, forkpty
, int *amaster
, char *name
, const void *termp
,
1236 ENSURE_MSAN_INITED();
1237 InterceptorScope interceptor_scope
;
1238 int res
= REAL(forkpty
)(amaster
, name
, termp
, winp
);
1240 __msan_unpoison(amaster
, sizeof(*amaster
));
1244 struct MSanInterceptorContext
{
1245 bool in_interceptor_scope
;
1251 // FIXME: ask frontend whether we need to return failure.
1255 } // namespace __msan
1257 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1259 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1261 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1262 CHECK_UNPOISONED_0(x, n); \
1265 #define MSAN_INTERCEPT_FUNC(name) \
1267 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
1268 VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \
1271 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1273 if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \
1275 1, "MemorySanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
1278 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1279 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1280 MSAN_INTERCEPT_FUNC_VER(name, ver)
1281 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1282 UnpoisonParam(count)
1283 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1284 __msan_unpoison(ptr, size)
1285 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1286 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1287 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1288 __msan_unpoison(ptr, size)
1289 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1290 if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \
1291 ENSURE_MSAN_INITED(); \
1292 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1293 ctx = (void *)&msan_ctx; \
1295 InterceptorScope interceptor_scope; \
1296 __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */
1297 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1300 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1303 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1306 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1309 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1311 } while (false) // FIXME
1312 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1314 } while (false) // FIXME
1315 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1316 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1317 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1319 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1320 if (filename && map) \
1321 ForEachMappedRegion(map, __msan_unpoison); \
1324 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1325 if (MsanThread *t = GetCurrentThread()) { \
1326 *begin = t->tls_begin(); \
1327 *end = t->tls_end(); \
1329 *begin = *end = 0; \
1332 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1333 // Msan needs custom handling of these:
1334 #undef SANITIZER_INTERCEPT_MEMSET
1335 #undef SANITIZER_INTERCEPT_MEMMOVE
1336 #undef SANITIZER_INTERCEPT_MEMCPY
1337 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1339 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1340 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1343 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1346 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1347 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1356 INTERCEPTOR(int, dladdr
, void *addr
, dlinfo
*info
) {
1358 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr
, addr
, info
);
1359 int res
= REAL(dladdr
)(addr
, info
);
1361 __msan_unpoison(info
, sizeof(*info
));
1362 if (info
->dli_fname
)
1363 __msan_unpoison(info
->dli_fname
, REAL(strlen
)(info
->dli_fname
) + 1);
1364 if (info
->dli_sname
)
1365 __msan_unpoison(info
->dli_sname
, REAL(strlen
)(info
->dli_sname
) + 1);
1370 INTERCEPTOR(char *, dlerror
, int fake
) {
1372 COMMON_INTERCEPTOR_ENTER(ctx
, dlerror
, fake
);
1373 char *res
= REAL(dlerror
)(fake
);
1374 if (res
) __msan_unpoison(res
, REAL(strlen
)(res
) + 1);
1378 typedef int (*dl_iterate_phdr_cb
)(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1380 struct dl_iterate_phdr_data
{
1381 dl_iterate_phdr_cb callback
;
1385 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1388 __msan_unpoison(info
, size
);
1389 if (info
->dlpi_phdr
&& info
->dlpi_phnum
)
1390 __msan_unpoison(info
->dlpi_phdr
, struct_ElfW_Phdr_sz
* info
->dlpi_phnum
);
1391 if (info
->dlpi_name
)
1392 __msan_unpoison(info
->dlpi_name
, REAL(strlen
)(info
->dlpi_name
) + 1);
1394 dl_iterate_phdr_data
*cbdata
= (dl_iterate_phdr_data
*)data
;
1396 return cbdata
->callback(info
, size
, cbdata
->data
);
1399 INTERCEPTOR(int, dl_iterate_phdr
, dl_iterate_phdr_cb callback
, void *data
) {
1401 COMMON_INTERCEPTOR_ENTER(ctx
, dl_iterate_phdr
, callback
, data
);
1402 dl_iterate_phdr_data cbdata
;
1403 cbdata
.callback
= callback
;
1405 int res
= REAL(dl_iterate_phdr
)(msan_dl_iterate_phdr_cb
, (void *)&cbdata
);
1409 // These interface functions reside here so that they can use
1410 // REAL(memset), etc.
1411 void __msan_unpoison(const void *a
, uptr size
) {
1412 if (!MEM_IS_APP(a
)) return;
1413 SetShadow(a
, size
, 0);
1416 void __msan_poison(const void *a
, uptr size
) {
1417 if (!MEM_IS_APP(a
)) return;
1418 SetShadow(a
, size
, __msan::flags()->poison_heap_with_zeroes
? 0 : -1);
1421 void __msan_poison_stack(void *a
, uptr size
) {
1422 if (!MEM_IS_APP(a
)) return;
1423 SetShadow(a
, size
, __msan::flags()->poison_stack_with_zeroes
? 0 : -1);
1426 void __msan_clear_and_unpoison(void *a
, uptr size
) {
1427 REAL(memset
)(a
, 0, size
);
1428 SetShadow(a
, size
, 0);
1431 void *__msan_memcpy(void *dest
, const void *src
, SIZE_T n
) {
1432 if (!msan_inited
) return internal_memcpy(dest
, src
, n
);
1433 if (msan_init_is_running
|| __msan::IsInSymbolizer())
1434 return REAL(memcpy
)(dest
, src
, n
);
1435 ENSURE_MSAN_INITED();
1436 GET_STORE_STACK_TRACE
;
1437 void *res
= REAL(memcpy
)(dest
, src
, n
);
1438 CopyShadowAndOrigin(dest
, src
, n
, &stack
);
1442 void *__msan_memset(void *s
, int c
, SIZE_T n
) {
1443 if (!msan_inited
) return internal_memset(s
, c
, n
);
1444 if (msan_init_is_running
) return REAL(memset
)(s
, c
, n
);
1445 ENSURE_MSAN_INITED();
1446 void *res
= REAL(memset
)(s
, c
, n
);
1447 __msan_unpoison(s
, n
);
1451 void *__msan_memmove(void *dest
, const void *src
, SIZE_T n
) {
1452 if (!msan_inited
) return internal_memmove(dest
, src
, n
);
1453 if (msan_init_is_running
) return REAL(memmove
)(dest
, src
, n
);
1454 ENSURE_MSAN_INITED();
1455 GET_STORE_STACK_TRACE
;
1456 void *res
= REAL(memmove
)(dest
, src
, n
);
1457 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1461 void __msan_unpoison_string(const char* s
) {
1462 if (!MEM_IS_APP(s
)) return;
1463 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
1468 void InitializeInterceptors() {
1469 static int inited
= 0;
1470 CHECK_EQ(inited
, 0);
1471 InitializeCommonInterceptors();
1473 INTERCEPT_FUNCTION(mmap
);
1474 MSAN_MAYBE_INTERCEPT_MMAP64
;
1475 INTERCEPT_FUNCTION(posix_memalign
);
1476 MSAN_MAYBE_INTERCEPT_MEMALIGN
;
1477 INTERCEPT_FUNCTION(__libc_memalign
);
1478 INTERCEPT_FUNCTION(valloc
);
1479 MSAN_MAYBE_INTERCEPT_PVALLOC
;
1480 INTERCEPT_FUNCTION(malloc
);
1481 INTERCEPT_FUNCTION(calloc
);
1482 INTERCEPT_FUNCTION(realloc
);
1483 INTERCEPT_FUNCTION(free
);
1484 MSAN_MAYBE_INTERCEPT_CFREE
;
1485 INTERCEPT_FUNCTION(malloc_usable_size
);
1486 MSAN_MAYBE_INTERCEPT_MALLINFO
;
1487 MSAN_MAYBE_INTERCEPT_MALLOPT
;
1488 MSAN_MAYBE_INTERCEPT_MALLOC_STATS
;
1489 INTERCEPT_FUNCTION(fread
);
1490 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
;
1491 INTERCEPT_FUNCTION(readlink
);
1492 INTERCEPT_FUNCTION(memcpy
);
1493 INTERCEPT_FUNCTION(memccpy
);
1494 INTERCEPT_FUNCTION(mempcpy
);
1495 INTERCEPT_FUNCTION(memset
);
1496 INTERCEPT_FUNCTION(memmove
);
1497 INTERCEPT_FUNCTION(bcopy
);
1498 INTERCEPT_FUNCTION(wmemset
);
1499 INTERCEPT_FUNCTION(wmemcpy
);
1500 INTERCEPT_FUNCTION(wmempcpy
);
1501 INTERCEPT_FUNCTION(wmemmove
);
1502 INTERCEPT_FUNCTION(strcpy
); // NOLINT
1503 INTERCEPT_FUNCTION(stpcpy
); // NOLINT
1504 INTERCEPT_FUNCTION(strdup
);
1505 MSAN_MAYBE_INTERCEPT___STRDUP
;
1506 INTERCEPT_FUNCTION(strndup
);
1507 MSAN_MAYBE_INTERCEPT___STRNDUP
;
1508 INTERCEPT_FUNCTION(strncpy
); // NOLINT
1509 INTERCEPT_FUNCTION(gcvt
);
1510 INTERCEPT_FUNCTION(strcat
); // NOLINT
1511 INTERCEPT_FUNCTION(strncat
); // NOLINT
1512 INTERCEPT_STRTO(strtod
);
1513 INTERCEPT_STRTO(strtof
);
1514 INTERCEPT_STRTO(strtold
);
1515 INTERCEPT_STRTO(strtol
);
1516 INTERCEPT_STRTO(strtoul
);
1517 INTERCEPT_STRTO(strtoll
);
1518 INTERCEPT_STRTO(strtoull
);
1519 INTERCEPT_STRTO(wcstod
);
1520 INTERCEPT_STRTO(wcstof
);
1521 INTERCEPT_STRTO(wcstold
);
1522 INTERCEPT_STRTO(wcstol
);
1523 INTERCEPT_STRTO(wcstoul
);
1524 INTERCEPT_STRTO(wcstoll
);
1525 INTERCEPT_STRTO(wcstoull
);
1526 #ifdef SANITIZER_NLDBL_VERSION
1527 INTERCEPT_FUNCTION_VER(vswprintf
, SANITIZER_NLDBL_VERSION
);
1528 INTERCEPT_FUNCTION_VER(swprintf
, SANITIZER_NLDBL_VERSION
);
1530 INTERCEPT_FUNCTION(vswprintf
);
1531 INTERCEPT_FUNCTION(swprintf
);
1533 INTERCEPT_FUNCTION(strxfrm
);
1534 INTERCEPT_FUNCTION(strxfrm_l
);
1535 INTERCEPT_FUNCTION(strftime
);
1536 INTERCEPT_FUNCTION(strftime_l
);
1537 MSAN_MAYBE_INTERCEPT___STRFTIME_L
;
1538 INTERCEPT_FUNCTION(wcsftime
);
1539 INTERCEPT_FUNCTION(wcsftime_l
);
1540 MSAN_MAYBE_INTERCEPT___WCSFTIME_L
;
1541 INTERCEPT_FUNCTION(mbtowc
);
1542 INTERCEPT_FUNCTION(mbrtowc
);
1543 INTERCEPT_FUNCTION(wcslen
);
1544 INTERCEPT_FUNCTION(wcschr
);
1545 INTERCEPT_FUNCTION(wcscpy
);
1546 INTERCEPT_FUNCTION(wcscmp
);
1547 INTERCEPT_FUNCTION(getenv
);
1548 INTERCEPT_FUNCTION(setenv
);
1549 INTERCEPT_FUNCTION(putenv
);
1550 INTERCEPT_FUNCTION(gettimeofday
);
1551 INTERCEPT_FUNCTION(fcvt
);
1552 MSAN_MAYBE_INTERCEPT___FXSTAT
;
1553 MSAN_INTERCEPT_FSTATAT
;
1554 MSAN_MAYBE_INTERCEPT___FXSTAT64
;
1555 MSAN_MAYBE_INTERCEPT___FXSTATAT64
;
1556 INTERCEPT_FUNCTION(pipe
);
1557 INTERCEPT_FUNCTION(pipe2
);
1558 INTERCEPT_FUNCTION(socketpair
);
1559 INTERCEPT_FUNCTION(fgets
);
1560 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
;
1561 INTERCEPT_FUNCTION(getrlimit
);
1562 MSAN_MAYBE_INTERCEPT_GETRLIMIT64
;
1563 MSAN_MAYBE_INTERCEPT_PRLIMIT
;
1564 MSAN_MAYBE_INTERCEPT_PRLIMIT64
;
1565 MSAN_INTERCEPT_UNAME
;
1566 INTERCEPT_FUNCTION(gethostname
);
1567 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
;
1568 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
;
1569 INTERCEPT_FUNCTION(dladdr
);
1570 INTERCEPT_FUNCTION(dlerror
);
1571 INTERCEPT_FUNCTION(dl_iterate_phdr
);
1572 INTERCEPT_FUNCTION(getrusage
);
1573 INTERCEPT_FUNCTION(sigaction
);
1574 INTERCEPT_FUNCTION(signal
);
1575 #if defined(__mips__)
1576 INTERCEPT_FUNCTION_VER(pthread_create
, "GLIBC_2.2");
1578 INTERCEPT_FUNCTION(pthread_create
);
1580 INTERCEPT_FUNCTION(pthread_key_create
);
1581 INTERCEPT_FUNCTION(pthread_join
);
1582 INTERCEPT_FUNCTION(tzset
);
1583 INTERCEPT_FUNCTION(__cxa_atexit
);
1584 INTERCEPT_FUNCTION(shmat
);
1585 INTERCEPT_FUNCTION(fork
);
1586 INTERCEPT_FUNCTION(openpty
);
1587 INTERCEPT_FUNCTION(forkpty
);
1591 } // namespace __msan