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 //===----------------------------------------------------------------------===//
19 #include "msan_thread.h"
20 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
21 #include "sanitizer_common/sanitizer_allocator.h"
22 #include "sanitizer_common/sanitizer_allocator_internal.h"
23 #include "sanitizer_common/sanitizer_atomic.h"
24 #include "sanitizer_common/sanitizer_common.h"
25 #include "sanitizer_common/sanitizer_interception.h"
26 #include "sanitizer_common/sanitizer_stackdepot.h"
27 #include "sanitizer_common/sanitizer_libc.h"
28 #include "sanitizer_common/sanitizer_linux.h"
31 // ACHTUNG! No other system header includes in this file.
32 // Ideally, we should get rid of stdarg.h as well.
34 using namespace __msan
;
36 using __sanitizer::memory_order
;
37 using __sanitizer::atomic_load
;
38 using __sanitizer::atomic_store
;
39 using __sanitizer::atomic_uintptr_t
;
41 // True if this is a nested interceptor.
42 static THREADLOCAL
int in_interceptor_scope
;
44 extern "C" int *__errno_location(void);
46 struct InterceptorScope
{
47 InterceptorScope() { ++in_interceptor_scope
; }
48 ~InterceptorScope() { --in_interceptor_scope
; }
51 bool IsInInterceptorScope() {
52 return in_interceptor_scope
;
55 #define ENSURE_MSAN_INITED() do { \
56 CHECK(!msan_init_is_running); \
62 // Check that [x, x+n) range is unpoisoned.
63 #define CHECK_UNPOISONED_0(x, n) \
65 sptr offset = __msan_test_shadow(x, n); \
66 if (__msan::IsInSymbolizer()) break; \
67 if (offset >= 0 && __msan::flags()->report_umrs) { \
68 GET_CALLER_PC_BP_SP; \
70 ReportUMRInsideAddressRange(__func__, x, n, offset); \
71 __msan::PrintWarningWithOrigin(pc, bp, \
72 __msan_get_origin((char *)x + offset)); \
73 if (__msan::flags()->halt_on_error) { \
74 Printf("Exiting\n"); \
80 // Check that [x, x+n) range is unpoisoned unless we are in a nested
82 #define CHECK_UNPOISONED(x, n) \
84 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
87 static void *fast_memset(void *ptr
, int c
, SIZE_T n
);
88 static void *fast_memcpy(void *dst
, const void *src
, SIZE_T n
);
90 INTERCEPTOR(SIZE_T
, fread
, void *ptr
, SIZE_T size
, SIZE_T nmemb
, void *file
) {
92 SIZE_T res
= REAL(fread
)(ptr
, size
, nmemb
, file
);
94 __msan_unpoison(ptr
, res
*size
);
98 INTERCEPTOR(SIZE_T
, fread_unlocked
, void *ptr
, SIZE_T size
, SIZE_T nmemb
,
100 ENSURE_MSAN_INITED();
101 SIZE_T res
= REAL(fread_unlocked
)(ptr
, size
, nmemb
, file
);
103 __msan_unpoison(ptr
, res
*size
);
107 INTERCEPTOR(SSIZE_T
, readlink
, const char *path
, char *buf
, SIZE_T bufsiz
) {
108 ENSURE_MSAN_INITED();
109 SSIZE_T res
= REAL(readlink
)(path
, buf
, bufsiz
);
111 __msan_unpoison(buf
, res
);
115 INTERCEPTOR(void *, memcpy
, void *dest
, const void *src
, SIZE_T n
) {
116 return __msan_memcpy(dest
, src
, n
);
119 INTERCEPTOR(void *, mempcpy
, void *dest
, const void *src
, SIZE_T n
) {
120 return (char *)__msan_memcpy(dest
, src
, n
) + n
;
123 INTERCEPTOR(void *, memccpy
, void *dest
, const void *src
, int c
, SIZE_T n
) {
124 ENSURE_MSAN_INITED();
125 void *res
= REAL(memccpy
)(dest
, src
, c
, n
);
126 CHECK(!res
|| (res
>= dest
&& res
<= (char *)dest
+ n
));
127 SIZE_T sz
= res
? (char *)res
- (char *)dest
: n
;
128 CHECK_UNPOISONED(src
, sz
);
129 __msan_unpoison(dest
, sz
);
133 INTERCEPTOR(void *, memmove
, void *dest
, const void *src
, SIZE_T n
) {
134 return __msan_memmove(dest
, src
, n
);
137 INTERCEPTOR(void *, memset
, void *s
, int c
, SIZE_T n
) {
138 return __msan_memset(s
, c
, n
);
141 INTERCEPTOR(void *, bcopy
, const void *src
, void *dest
, SIZE_T n
) {
142 return __msan_memmove(dest
, src
, n
);
145 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
146 GET_MALLOC_STACK_TRACE
;
147 CHECK_EQ(alignment
& (alignment
- 1), 0);
149 *memptr
= MsanReallocate(&stack
, 0, size
, alignment
, false);
150 CHECK_NE(*memptr
, 0);
151 __msan_unpoison(memptr
, sizeof(*memptr
));
155 INTERCEPTOR(void *, memalign
, SIZE_T boundary
, SIZE_T size
) {
156 GET_MALLOC_STACK_TRACE
;
157 CHECK_EQ(boundary
& (boundary
- 1), 0);
158 void *ptr
= MsanReallocate(&stack
, 0, size
, boundary
, false);
162 INTERCEPTOR(void *, __libc_memalign
, uptr align
, uptr s
)
163 ALIAS(WRAPPER_NAME(memalign
));
165 INTERCEPTOR(void *, valloc
, SIZE_T size
) {
166 GET_MALLOC_STACK_TRACE
;
167 void *ptr
= MsanReallocate(&stack
, 0, size
, GetPageSizeCached(), false);
171 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
172 GET_MALLOC_STACK_TRACE
;
173 uptr PageSize
= GetPageSizeCached();
174 size
= RoundUpTo(size
, PageSize
);
176 // pvalloc(0) should allocate one page.
179 void *ptr
= MsanReallocate(&stack
, 0, size
, PageSize
, false);
183 INTERCEPTOR(void, free
, void *ptr
) {
184 GET_MALLOC_STACK_TRACE
;
185 if (ptr
== 0) return;
186 MsanDeallocate(&stack
, ptr
);
189 INTERCEPTOR(void, cfree
, void *ptr
) {
190 GET_MALLOC_STACK_TRACE
;
191 if (ptr
== 0) return;
192 MsanDeallocate(&stack
, ptr
);
195 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
196 return __msan_get_allocated_size(ptr
);
199 // This function actually returns a struct by value, but we can't unpoison a
200 // temporary! The following is equivalent on all supported platforms, and we
201 // have a test to confirm that.
202 INTERCEPTOR(void, mallinfo
, __sanitizer_mallinfo
*sret
) {
203 REAL(memset
)(sret
, 0, sizeof(*sret
));
204 __msan_unpoison(sret
, sizeof(*sret
));
207 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
211 INTERCEPTOR(void, malloc_stats
, void) {
212 // FIXME: implement, but don't call REAL(malloc_stats)!
215 INTERCEPTOR(SIZE_T
, strlen
, const char *s
) {
216 ENSURE_MSAN_INITED();
217 SIZE_T res
= REAL(strlen
)(s
);
218 CHECK_UNPOISONED(s
, res
+ 1);
222 INTERCEPTOR(SIZE_T
, strnlen
, const char *s
, SIZE_T n
) {
223 ENSURE_MSAN_INITED();
224 SIZE_T res
= REAL(strnlen
)(s
, n
);
225 SIZE_T scan_size
= (res
== n
) ? res
: res
+ 1;
226 CHECK_UNPOISONED(s
, scan_size
);
230 // FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should
231 // check the shadow of the terminating \0 byte).
233 INTERCEPTOR(char *, strcpy
, char *dest
, const char *src
) { // NOLINT
234 ENSURE_MSAN_INITED();
235 GET_STORE_STACK_TRACE
;
236 SIZE_T n
= REAL(strlen
)(src
);
237 char *res
= REAL(strcpy
)(dest
, src
); // NOLINT
238 CopyPoison(dest
, src
, n
+ 1, &stack
);
242 INTERCEPTOR(char *, strncpy
, char *dest
, const char *src
, SIZE_T n
) { // NOLINT
243 ENSURE_MSAN_INITED();
244 GET_STORE_STACK_TRACE
;
245 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
247 copy_size
++; // trailing \0
248 char *res
= REAL(strncpy
)(dest
, src
, n
); // NOLINT
249 CopyPoison(dest
, src
, copy_size
, &stack
);
253 INTERCEPTOR(char *, stpcpy
, char *dest
, const char *src
) { // NOLINT
254 ENSURE_MSAN_INITED();
255 GET_STORE_STACK_TRACE
;
256 SIZE_T n
= REAL(strlen
)(src
);
257 char *res
= REAL(stpcpy
)(dest
, src
); // NOLINT
258 CopyPoison(dest
, src
, n
+ 1, &stack
);
262 INTERCEPTOR(char *, strdup
, char *src
) {
263 ENSURE_MSAN_INITED();
264 GET_STORE_STACK_TRACE
;
265 SIZE_T n
= REAL(strlen
)(src
);
266 char *res
= REAL(strdup
)(src
);
267 CopyPoison(res
, src
, n
+ 1, &stack
);
271 INTERCEPTOR(char *, __strdup
, char *src
) {
272 ENSURE_MSAN_INITED();
273 GET_STORE_STACK_TRACE
;
274 SIZE_T n
= REAL(strlen
)(src
);
275 char *res
= REAL(__strdup
)(src
);
276 CopyPoison(res
, src
, n
+ 1, &stack
);
280 INTERCEPTOR(char *, strndup
, char *src
, SIZE_T n
) {
281 ENSURE_MSAN_INITED();
282 GET_STORE_STACK_TRACE
;
283 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
284 char *res
= REAL(strndup
)(src
, n
);
285 CopyPoison(res
, src
, copy_size
, &stack
);
286 __msan_unpoison(res
+ copy_size
, 1); // \0
290 INTERCEPTOR(char *, __strndup
, char *src
, SIZE_T n
) {
291 ENSURE_MSAN_INITED();
292 GET_STORE_STACK_TRACE
;
293 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
294 char *res
= REAL(__strndup
)(src
, n
);
295 CopyPoison(res
, src
, copy_size
, &stack
);
296 __msan_unpoison(res
+ copy_size
, 1); // \0
300 INTERCEPTOR(char *, gcvt
, double number
, SIZE_T ndigit
, char *buf
) {
301 ENSURE_MSAN_INITED();
302 char *res
= REAL(gcvt
)(number
, ndigit
, buf
);
303 // DynamoRio tool will take care of unpoisoning gcvt result for us.
304 if (!__msan_has_dynamic_component()) {
305 SIZE_T n
= REAL(strlen
)(buf
);
306 __msan_unpoison(buf
, n
+ 1);
311 INTERCEPTOR(char *, strcat
, char *dest
, const char *src
) { // NOLINT
312 ENSURE_MSAN_INITED();
313 GET_STORE_STACK_TRACE
;
314 SIZE_T src_size
= REAL(strlen
)(src
);
315 SIZE_T dest_size
= REAL(strlen
)(dest
);
316 char *res
= REAL(strcat
)(dest
, src
); // NOLINT
317 CopyPoison(dest
+ dest_size
, src
, src_size
+ 1, &stack
);
321 INTERCEPTOR(char *, strncat
, char *dest
, const char *src
, SIZE_T n
) { // NOLINT
322 ENSURE_MSAN_INITED();
323 GET_STORE_STACK_TRACE
;
324 SIZE_T dest_size
= REAL(strlen
)(dest
);
325 SIZE_T copy_size
= REAL(strnlen
)(src
, n
);
326 char *res
= REAL(strncat
)(dest
, src
, n
); // NOLINT
327 CopyPoison(dest
+ dest_size
, src
, copy_size
, &stack
);
328 __msan_unpoison(dest
+ dest_size
+ copy_size
, 1); // \0
332 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
333 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
334 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
335 ENSURE_MSAN_INITED(); \
336 ret_type res = REAL(func)(__VA_ARGS__); \
337 if (!__msan_has_dynamic_component()) { \
338 __msan_unpoison(endptr, sizeof(*endptr)); \
342 #define INTERCEPTOR_STRTO(ret_type, func) \
343 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr) { \
344 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
347 #define INTERCEPTOR_STRTO_BASE(ret_type, func) \
348 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
349 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
352 #define INTERCEPTOR_STRTO_LOC(ret_type, func) \
353 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, void *loc) { \
354 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
357 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func) \
358 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base, \
360 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
363 INTERCEPTOR_STRTO(double, strtod
) // NOLINT
364 INTERCEPTOR_STRTO(float, strtof
) // NOLINT
365 INTERCEPTOR_STRTO(long double, strtold
) // NOLINT
366 INTERCEPTOR_STRTO_BASE(long, strtol
) // NOLINT
367 INTERCEPTOR_STRTO_BASE(long long, strtoll
) // NOLINT
368 INTERCEPTOR_STRTO_BASE(unsigned long, strtoul
) // NOLINT
369 INTERCEPTOR_STRTO_BASE(unsigned long long, strtoull
) // NOLINT
370 INTERCEPTOR_STRTO_LOC(double, strtod_l
) // NOLINT
371 INTERCEPTOR_STRTO_LOC(double, __strtod_l
) // NOLINT
372 INTERCEPTOR_STRTO_LOC(float, strtof_l
) // NOLINT
373 INTERCEPTOR_STRTO_LOC(float, __strtof_l
) // NOLINT
374 INTERCEPTOR_STRTO_LOC(long double, strtold_l
) // NOLINT
375 INTERCEPTOR_STRTO_LOC(long double, __strtold_l
) // NOLINT
376 INTERCEPTOR_STRTO_BASE_LOC(long, strtol_l
) // NOLINT
377 INTERCEPTOR_STRTO_BASE_LOC(long long, strtoll_l
) // NOLINT
378 INTERCEPTOR_STRTO_BASE_LOC(unsigned long, strtoul_l
) // NOLINT
379 INTERCEPTOR_STRTO_BASE_LOC(unsigned long long, strtoull_l
) // NOLINT
381 // FIXME: support *wprintf in common format interceptors.
382 INTERCEPTOR(int, vswprintf
, void *str
, uptr size
, void *format
, va_list ap
) {
383 ENSURE_MSAN_INITED();
384 int res
= REAL(vswprintf
)(str
, size
, format
, ap
);
385 if (res
>= 0 && !__msan_has_dynamic_component()) {
386 __msan_unpoison(str
, 4 * (res
+ 1));
391 INTERCEPTOR(int, swprintf
, void *str
, uptr size
, void *format
, ...) {
392 ENSURE_MSAN_INITED();
394 va_start(ap
, format
);
395 int res
= vswprintf(str
, size
, format
, ap
);
400 INTERCEPTOR(SIZE_T
, strxfrm
, char *dest
, const char *src
, SIZE_T n
) {
401 ENSURE_MSAN_INITED();
402 CHECK_UNPOISONED(src
, REAL(strlen
)(src
) + 1);
403 SIZE_T res
= REAL(strxfrm
)(dest
, src
, n
);
404 if (res
< n
) __msan_unpoison(dest
, res
+ 1);
408 INTERCEPTOR(SIZE_T
, strxfrm_l
, char *dest
, const char *src
, SIZE_T n
,
410 ENSURE_MSAN_INITED();
411 CHECK_UNPOISONED(src
, REAL(strlen
)(src
) + 1);
412 SIZE_T res
= REAL(strxfrm_l
)(dest
, src
, n
, loc
);
413 if (res
< n
) __msan_unpoison(dest
, res
+ 1);
417 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
418 ENSURE_MSAN_INITED(); \
419 ret_type res = REAL(func)(s, __VA_ARGS__); \
420 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
423 INTERCEPTOR(SIZE_T
, strftime
, char *s
, SIZE_T max
, const char *format
,
424 __sanitizer_tm
*tm
) {
425 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime
, s
, max
, format
, tm
);
428 INTERCEPTOR(SIZE_T
, strftime_l
, char *s
, SIZE_T max
, const char *format
,
429 __sanitizer_tm
*tm
, void *loc
) {
430 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime_l
, s
, max
, format
, tm
, loc
);
433 INTERCEPTOR(SIZE_T
, __strftime_l
, char *s
, SIZE_T max
, const char *format
,
434 __sanitizer_tm
*tm
, void *loc
) {
435 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, __strftime_l
, s
, max
, format
, tm
,
439 INTERCEPTOR(SIZE_T
, wcsftime
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
440 __sanitizer_tm
*tm
) {
441 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime
, s
, max
, format
, tm
);
444 INTERCEPTOR(SIZE_T
, wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
445 __sanitizer_tm
*tm
, void *loc
) {
446 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime_l
, s
, max
, format
, tm
,
450 INTERCEPTOR(SIZE_T
, __wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
451 __sanitizer_tm
*tm
, void *loc
) {
452 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, __wcsftime_l
, s
, max
, format
, tm
,
456 INTERCEPTOR(int, mbtowc
, wchar_t *dest
, const char *src
, SIZE_T n
) {
457 ENSURE_MSAN_INITED();
458 int res
= REAL(mbtowc
)(dest
, src
, n
);
459 if (res
!= -1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
463 INTERCEPTOR(int, mbrtowc
, wchar_t *dest
, const char *src
, SIZE_T n
, void *ps
) {
464 ENSURE_MSAN_INITED();
465 SIZE_T res
= REAL(mbrtowc
)(dest
, src
, n
, ps
);
466 if (res
!= (SIZE_T
)-1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
470 INTERCEPTOR(SIZE_T
, wcslen
, const wchar_t *s
) {
471 ENSURE_MSAN_INITED();
472 SIZE_T res
= REAL(wcslen
)(s
);
473 CHECK_UNPOISONED(s
, sizeof(wchar_t) * (res
+ 1));
477 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
478 INTERCEPTOR(wchar_t *, wcschr
, void *s
, wchar_t wc
, void *ps
) {
479 ENSURE_MSAN_INITED();
480 wchar_t *res
= REAL(wcschr
)(s
, wc
, ps
);
484 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
485 INTERCEPTOR(wchar_t *, wcscpy
, wchar_t *dest
, const wchar_t *src
) {
486 ENSURE_MSAN_INITED();
487 GET_STORE_STACK_TRACE
;
488 wchar_t *res
= REAL(wcscpy
)(dest
, src
);
489 CopyPoison(dest
, src
, sizeof(wchar_t) * (REAL(wcslen
)(src
) + 1), &stack
);
493 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
494 INTERCEPTOR(wchar_t *, wmemcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
495 ENSURE_MSAN_INITED();
496 GET_STORE_STACK_TRACE
;
497 wchar_t *res
= REAL(wmemcpy
)(dest
, src
, n
);
498 CopyPoison(dest
, src
, n
* sizeof(wchar_t), &stack
);
502 INTERCEPTOR(wchar_t *, wmempcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
503 ENSURE_MSAN_INITED();
504 GET_STORE_STACK_TRACE
;
505 wchar_t *res
= REAL(wmempcpy
)(dest
, src
, n
);
506 CopyPoison(dest
, src
, n
* sizeof(wchar_t), &stack
);
510 INTERCEPTOR(wchar_t *, wmemset
, wchar_t *s
, wchar_t c
, SIZE_T n
) {
511 CHECK(MEM_IS_APP(s
));
512 ENSURE_MSAN_INITED();
513 wchar_t *res
= (wchar_t *)fast_memset(s
, c
, n
* sizeof(wchar_t));
514 __msan_unpoison(s
, n
* sizeof(wchar_t));
518 INTERCEPTOR(wchar_t *, wmemmove
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
519 ENSURE_MSAN_INITED();
520 GET_STORE_STACK_TRACE
;
521 wchar_t *res
= REAL(wmemmove
)(dest
, src
, n
);
522 MovePoison(dest
, src
, n
* sizeof(wchar_t), &stack
);
526 INTERCEPTOR(int, wcscmp
, const wchar_t *s1
, const wchar_t *s2
) {
527 ENSURE_MSAN_INITED();
528 int res
= REAL(wcscmp
)(s1
, s2
);
532 INTERCEPTOR(double, wcstod
, const wchar_t *nptr
, wchar_t **endptr
) {
533 ENSURE_MSAN_INITED();
534 double res
= REAL(wcstod
)(nptr
, endptr
);
535 __msan_unpoison(endptr
, sizeof(*endptr
));
539 INTERCEPTOR(int, gettimeofday
, void *tv
, void *tz
) {
540 ENSURE_MSAN_INITED();
541 int res
= REAL(gettimeofday
)(tv
, tz
);
543 __msan_unpoison(tv
, 16);
545 __msan_unpoison(tz
, 8);
549 INTERCEPTOR(char *, fcvt
, double x
, int a
, int *b
, int *c
) {
550 ENSURE_MSAN_INITED();
551 char *res
= REAL(fcvt
)(x
, a
, b
, c
);
552 if (!__msan_has_dynamic_component()) {
553 __msan_unpoison(b
, sizeof(*b
));
554 __msan_unpoison(c
, sizeof(*c
));
559 INTERCEPTOR(char *, getenv
, char *name
) {
560 ENSURE_MSAN_INITED();
561 char *res
= REAL(getenv
)(name
);
562 if (!__msan_has_dynamic_component()) {
564 __msan_unpoison(res
, REAL(strlen
)(res
) + 1);
569 extern char **environ
;
571 static void UnpoisonEnviron() {
572 char **envp
= environ
;
573 for (; *envp
; ++envp
) {
574 __msan_unpoison(envp
, sizeof(*envp
));
575 __msan_unpoison(*envp
, REAL(strlen
)(*envp
) + 1);
577 // Trailing NULL pointer.
578 __msan_unpoison(envp
, sizeof(*envp
));
581 INTERCEPTOR(int, setenv
, const char *name
, const char *value
, int overwrite
) {
582 ENSURE_MSAN_INITED();
583 int res
= REAL(setenv
)(name
, value
, overwrite
);
584 if (!res
) UnpoisonEnviron();
588 INTERCEPTOR(int, putenv
, char *string
) {
589 ENSURE_MSAN_INITED();
590 int res
= REAL(putenv
)(string
);
591 if (!res
) UnpoisonEnviron();
595 INTERCEPTOR(int, __fxstat
, int magic
, int fd
, void *buf
) {
596 ENSURE_MSAN_INITED();
597 int res
= REAL(__fxstat
)(magic
, fd
, buf
);
599 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
603 INTERCEPTOR(int, __fxstat64
, int magic
, int fd
, void *buf
) {
604 ENSURE_MSAN_INITED();
605 int res
= REAL(__fxstat64
)(magic
, fd
, buf
);
607 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
611 INTERCEPTOR(int, __fxstatat
, int magic
, int fd
, char *pathname
, void *buf
,
613 ENSURE_MSAN_INITED();
614 int res
= REAL(__fxstatat
)(magic
, fd
, pathname
, buf
, flags
);
615 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
619 INTERCEPTOR(int, __fxstatat64
, int magic
, int fd
, char *pathname
, void *buf
,
621 ENSURE_MSAN_INITED();
622 int res
= REAL(__fxstatat64
)(magic
, fd
, pathname
, buf
, flags
);
623 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
627 INTERCEPTOR(int, __xstat
, int magic
, char *path
, void *buf
) {
628 ENSURE_MSAN_INITED();
629 int res
= REAL(__xstat
)(magic
, path
, buf
);
631 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
635 INTERCEPTOR(int, __xstat64
, int magic
, char *path
, void *buf
) {
636 ENSURE_MSAN_INITED();
637 int res
= REAL(__xstat64
)(magic
, path
, buf
);
639 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
643 INTERCEPTOR(int, __lxstat
, int magic
, char *path
, void *buf
) {
644 ENSURE_MSAN_INITED();
645 int res
= REAL(__lxstat
)(magic
, path
, buf
);
647 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
651 INTERCEPTOR(int, __lxstat64
, int magic
, char *path
, void *buf
) {
652 ENSURE_MSAN_INITED();
653 int res
= REAL(__lxstat64
)(magic
, path
, buf
);
655 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
659 INTERCEPTOR(int, pipe
, int pipefd
[2]) {
660 if (msan_init_is_running
)
661 return REAL(pipe
)(pipefd
);
662 ENSURE_MSAN_INITED();
663 int res
= REAL(pipe
)(pipefd
);
665 __msan_unpoison(pipefd
, sizeof(int[2]));
669 INTERCEPTOR(int, pipe2
, int pipefd
[2], int flags
) {
670 ENSURE_MSAN_INITED();
671 int res
= REAL(pipe2
)(pipefd
, flags
);
673 __msan_unpoison(pipefd
, sizeof(int[2]));
677 INTERCEPTOR(int, socketpair
, int domain
, int type
, int protocol
, int sv
[2]) {
678 ENSURE_MSAN_INITED();
679 int res
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
681 __msan_unpoison(sv
, sizeof(int[2]));
685 INTERCEPTOR(char *, fgets
, char *s
, int size
, void *stream
) {
686 ENSURE_MSAN_INITED();
687 char *res
= REAL(fgets
)(s
, size
, stream
);
689 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
693 INTERCEPTOR(char *, fgets_unlocked
, char *s
, int size
, void *stream
) {
694 ENSURE_MSAN_INITED();
695 char *res
= REAL(fgets_unlocked
)(s
, size
, stream
);
697 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
701 INTERCEPTOR(int, getrlimit
, int resource
, void *rlim
) {
702 if (msan_init_is_running
)
703 return REAL(getrlimit
)(resource
, rlim
);
704 ENSURE_MSAN_INITED();
705 int res
= REAL(getrlimit
)(resource
, rlim
);
707 __msan_unpoison(rlim
, __sanitizer::struct_rlimit_sz
);
711 INTERCEPTOR(int, getrlimit64
, int resource
, void *rlim
) {
712 if (msan_init_is_running
)
713 return REAL(getrlimit64
)(resource
, rlim
);
714 ENSURE_MSAN_INITED();
715 int res
= REAL(getrlimit64
)(resource
, rlim
);
717 __msan_unpoison(rlim
, __sanitizer::struct_rlimit64_sz
);
721 INTERCEPTOR(int, uname
, void *utsname
) {
722 ENSURE_MSAN_INITED();
723 int res
= REAL(uname
)(utsname
);
725 __msan_unpoison(utsname
, __sanitizer::struct_utsname_sz
);
730 INTERCEPTOR(int, gethostname
, char *name
, SIZE_T len
) {
731 ENSURE_MSAN_INITED();
732 int res
= REAL(gethostname
)(name
, len
);
734 SIZE_T real_len
= REAL(strnlen
)(name
, len
);
737 __msan_unpoison(name
, real_len
);
742 INTERCEPTOR(int, epoll_wait
, int epfd
, void *events
, int maxevents
,
744 ENSURE_MSAN_INITED();
745 int res
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
747 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
752 INTERCEPTOR(int, epoll_pwait
, int epfd
, void *events
, int maxevents
,
753 int timeout
, void *sigmask
) {
754 ENSURE_MSAN_INITED();
755 int res
= REAL(epoll_pwait
)(epfd
, events
, maxevents
, timeout
, sigmask
);
757 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
762 INTERCEPTOR(SSIZE_T
, recv
, int fd
, void *buf
, SIZE_T len
, int flags
) {
763 ENSURE_MSAN_INITED();
764 SSIZE_T res
= REAL(recv
)(fd
, buf
, len
, flags
);
766 __msan_unpoison(buf
, res
);
770 INTERCEPTOR(SSIZE_T
, recvfrom
, int fd
, void *buf
, SIZE_T len
, int flags
,
771 void *srcaddr
, int *addrlen
) {
772 ENSURE_MSAN_INITED();
774 if (srcaddr
) srcaddr_sz
= *addrlen
;
775 SSIZE_T res
= REAL(recvfrom
)(fd
, buf
, len
, flags
, srcaddr
, addrlen
);
777 __msan_unpoison(buf
, res
);
779 SIZE_T sz
= *addrlen
;
780 __msan_unpoison(srcaddr
, (sz
< srcaddr_sz
) ? sz
: srcaddr_sz
);
786 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
787 if (CallocShouldReturnNullDueToOverflow(size
, nmemb
))
788 return AllocatorReturnNull();
789 GET_MALLOC_STACK_TRACE
;
791 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
792 const SIZE_T kCallocPoolSize
= 1024;
793 static uptr calloc_memory_for_dlsym
[kCallocPoolSize
];
794 static SIZE_T allocated
;
795 SIZE_T size_in_words
= ((nmemb
* size
) + kWordSize
- 1) / kWordSize
;
796 void *mem
= (void*)&calloc_memory_for_dlsym
[allocated
];
797 allocated
+= size_in_words
;
798 CHECK(allocated
< kCallocPoolSize
);
801 return MsanReallocate(&stack
, 0, nmemb
* size
, sizeof(u64
), true);
804 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
805 GET_MALLOC_STACK_TRACE
;
806 return MsanReallocate(&stack
, ptr
, size
, sizeof(u64
), false);
809 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
810 GET_MALLOC_STACK_TRACE
;
811 return MsanReallocate(&stack
, 0, size
, sizeof(u64
), false);
814 void __msan_allocated_memory(const void* data
, uptr size
) {
815 GET_MALLOC_STACK_TRACE
;
816 if (flags()->poison_in_malloc
)
817 __msan_poison(data
, size
);
818 if (__msan_get_track_origins()) {
819 u32 stack_id
= StackDepotPut(stack
.trace
, stack
.size
);
821 CHECK_EQ((stack_id
>> 31), 0); // Higher bit is occupied by stack origins.
822 __msan_set_origin(data
, size
, stack_id
);
826 INTERCEPTOR(void *, mmap
, void *addr
, SIZE_T length
, int prot
, int flags
,
827 int fd
, OFF_T offset
) {
828 ENSURE_MSAN_INITED();
829 if (addr
&& !MEM_IS_APP(addr
)) {
830 if (flags
& map_fixed
) {
831 *__errno_location() = errno_EINVAL
;
837 void *res
= REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
838 if (res
!= (void*)-1)
839 __msan_unpoison(res
, RoundUpTo(length
, GetPageSize()));
843 INTERCEPTOR(void *, mmap64
, void *addr
, SIZE_T length
, int prot
, int flags
,
844 int fd
, OFF64_T offset
) {
845 ENSURE_MSAN_INITED();
846 if (addr
&& !MEM_IS_APP(addr
)) {
847 if (flags
& map_fixed
) {
848 *__errno_location() = errno_EINVAL
;
854 void *res
= REAL(mmap64
)(addr
, length
, prot
, flags
, fd
, offset
);
855 if (res
!= (void*)-1)
856 __msan_unpoison(res
, RoundUpTo(length
, GetPageSize()));
867 INTERCEPTOR(int, dladdr
, void *addr
, dlinfo
*info
) {
868 ENSURE_MSAN_INITED();
869 int res
= REAL(dladdr
)(addr
, info
);
871 __msan_unpoison(info
, sizeof(*info
));
873 __msan_unpoison(info
->dli_fname
, REAL(strlen
)(info
->dli_fname
) + 1);
875 __msan_unpoison(info
->dli_sname
, REAL(strlen
)(info
->dli_sname
) + 1);
880 INTERCEPTOR(char *, dlerror
, int fake
) {
881 ENSURE_MSAN_INITED();
882 char *res
= REAL(dlerror
)(fake
);
883 if (res
!= 0) __msan_unpoison(res
, REAL(strlen
)(res
) + 1);
887 // dlopen() ultimately calls mmap() down inside the loader, which generally
888 // doesn't participate in dynamic symbol resolution. Therefore we won't
889 // intercept its calls to mmap, and we have to hook it here. The loader
890 // initializes the module before returning, so without the dynamic component, we
891 // won't be able to clear the shadow before the initializers. Fixing this would
892 // require putting our own initializer first to clear the shadow.
893 INTERCEPTOR(void *, dlopen
, const char *filename
, int flag
) {
894 ENSURE_MSAN_INITED();
896 link_map
*map
= (link_map
*)REAL(dlopen
)(filename
, flag
);
898 if (!__msan_has_dynamic_component() && map
) {
899 // If msandr didn't clear the shadow before the initializers ran, we do it
900 // ourselves afterwards.
901 ForEachMappedRegion(map
, __msan_unpoison
);
906 typedef int (*dl_iterate_phdr_cb
)(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
908 struct dl_iterate_phdr_data
{
909 dl_iterate_phdr_cb callback
;
913 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
916 __msan_unpoison(info
, size
);
918 __msan_unpoison(info
->dlpi_name
, REAL(strlen
)(info
->dlpi_name
) + 1);
920 dl_iterate_phdr_data
*cbdata
= (dl_iterate_phdr_data
*)data
;
922 return IndirectExternCall(cbdata
->callback
)(info
, size
, cbdata
->data
);
925 INTERCEPTOR(int, dl_iterate_phdr
, dl_iterate_phdr_cb callback
, void *data
) {
926 ENSURE_MSAN_INITED();
928 dl_iterate_phdr_data cbdata
;
929 cbdata
.callback
= callback
;
931 int res
= REAL(dl_iterate_phdr
)(msan_dl_iterate_phdr_cb
, (void *)&cbdata
);
936 INTERCEPTOR(int, getrusage
, int who
, void *usage
) {
937 ENSURE_MSAN_INITED();
938 int res
= REAL(getrusage
)(who
, usage
);
940 __msan_unpoison(usage
, __sanitizer::struct_rusage_sz
);
945 class SignalHandlerScope
{
947 SignalHandlerScope() {
948 if (MsanThread
*t
= GetCurrentThread())
949 t
->EnterSignalHandler();
951 ~SignalHandlerScope() {
952 if (MsanThread
*t
= GetCurrentThread())
953 t
->LeaveSignalHandler();
957 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
958 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
959 // the signal handler.
960 const int kMaxSignals
= 1024;
961 static atomic_uintptr_t sigactions
[kMaxSignals
];
962 static StaticSpinMutex sigactions_mu
;
964 static void SignalHandler(int signo
) {
965 SignalHandlerScope signal_handler_scope
;
966 ScopedThreadLocalStateBackup stlsb
;
969 typedef void (*signal_cb
)(int x
);
971 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
972 IndirectExternCall(cb
)(signo
);
975 static void SignalAction(int signo
, void *si
, void *uc
) {
976 SignalHandlerScope signal_handler_scope
;
977 ScopedThreadLocalStateBackup stlsb
;
979 __msan_unpoison(si
, sizeof(__sanitizer_sigaction
));
980 __msan_unpoison(uc
, __sanitizer::ucontext_t_sz
);
982 typedef void (*sigaction_cb
)(int, void *, void *);
984 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
985 IndirectExternCall(cb
)(signo
, si
, uc
);
988 INTERCEPTOR(int, sigaction
, int signo
, const __sanitizer_sigaction
*act
,
989 __sanitizer_sigaction
*oldact
) {
990 ENSURE_MSAN_INITED();
991 // FIXME: check that *act is unpoisoned.
992 // That requires intercepting all of sigemptyset, sigfillset, etc.
994 if (flags()->wrap_signals
) {
995 SpinMutexLock
lock(&sigactions_mu
);
996 CHECK_LT(signo
, kMaxSignals
);
997 uptr old_cb
= atomic_load(&sigactions
[signo
], memory_order_relaxed
);
998 __sanitizer_sigaction new_act
;
999 __sanitizer_sigaction
*pnew_act
= act
? &new_act
: 0;
1001 internal_memcpy(pnew_act
, act
, sizeof(__sanitizer_sigaction
));
1002 uptr cb
= (uptr
)pnew_act
->sigaction
;
1003 uptr new_cb
= (pnew_act
->sa_flags
& __sanitizer::sa_siginfo
)
1004 ? (uptr
)SignalAction
1005 : (uptr
)SignalHandler
;
1006 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1007 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1008 pnew_act
->sigaction
= (void (*)(int, void *, void *))new_cb
;
1011 res
= REAL(sigaction
)(signo
, pnew_act
, oldact
);
1012 if (res
== 0 && oldact
) {
1013 uptr cb
= (uptr
)oldact
->sigaction
;
1014 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1015 oldact
->sigaction
= (void (*)(int, void *, void *))old_cb
;
1019 res
= REAL(sigaction
)(signo
, act
, oldact
);
1022 if (res
== 0 && oldact
) {
1023 __msan_unpoison(oldact
, sizeof(__sanitizer_sigaction
));
1028 INTERCEPTOR(int, signal
, int signo
, uptr cb
) {
1029 ENSURE_MSAN_INITED();
1030 if (flags()->wrap_signals
) {
1031 CHECK_LT(signo
, kMaxSignals
);
1032 SpinMutexLock
lock(&sigactions_mu
);
1033 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1034 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1035 cb
= (uptr
) SignalHandler
;
1037 return REAL(signal
)(signo
, cb
);
1039 return REAL(signal
)(signo
, cb
);
1043 extern "C" int pthread_attr_init(void *attr
);
1044 extern "C" int pthread_attr_destroy(void *attr
);
1046 static void *MsanThreadStartFunc(void *arg
) {
1047 MsanThread
*t
= (MsanThread
*)arg
;
1048 SetCurrentThread(t
);
1049 return t
->ThreadStart();
1052 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
, void *(*callback
)(void*),
1054 ENSURE_MSAN_INITED(); // for GetTlsSize()
1055 __sanitizer_pthread_attr_t myattr
;
1057 pthread_attr_init(&myattr
);
1061 AdjustStackSize(attr
);
1063 MsanThread
*t
= MsanThread::Create(callback
, param
);
1065 int res
= REAL(pthread_create
)(th
, attr
, MsanThreadStartFunc
, t
);
1067 if (attr
== &myattr
)
1068 pthread_attr_destroy(&myattr
);
1070 __msan_unpoison(th
, __sanitizer::pthread_t_sz
);
1075 INTERCEPTOR(int, pthread_key_create
, __sanitizer_pthread_key_t
*key
,
1076 void (*dtor
)(void *value
)) {
1077 if (msan_init_is_running
) return REAL(pthread_key_create
)(key
, dtor
);
1078 ENSURE_MSAN_INITED();
1079 int res
= REAL(pthread_key_create
)(key
, dtor
);
1081 __msan_unpoison(key
, sizeof(*key
));
1085 INTERCEPTOR(int, pthread_join
, void *th
, void **retval
) {
1086 ENSURE_MSAN_INITED();
1087 int res
= REAL(pthread_join
)(th
, retval
);
1089 __msan_unpoison(retval
, sizeof(*retval
));
1093 extern char *tzname
[2];
1095 INTERCEPTOR(void, tzset
, int fake
) {
1096 ENSURE_MSAN_INITED();
1099 __msan_unpoison(tzname
[0], REAL(strlen
)(tzname
[0]) + 1);
1101 __msan_unpoison(tzname
[1], REAL(strlen
)(tzname
[1]) + 1);
1105 struct MSanAtExitRecord
{
1106 void (*func
)(void *arg
);
1110 void MSanAtExitWrapper(void *arg
) {
1112 MSanAtExitRecord
*r
= (MSanAtExitRecord
*)arg
;
1113 IndirectExternCall(r
->func
)(r
->arg
);
1117 // Unpoison argument shadow for C++ module destructors.
1118 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
1120 if (msan_init_is_running
) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
1121 ENSURE_MSAN_INITED();
1122 MSanAtExitRecord
*r
=
1123 (MSanAtExitRecord
*)InternalAlloc(sizeof(MSanAtExitRecord
));
1126 return REAL(__cxa_atexit
)(MSanAtExitWrapper
, r
, dso_handle
);
1129 DECLARE_REAL(int, shmctl
, int shmid
, int cmd
, void *buf
)
1131 INTERCEPTOR(void *, shmat
, int shmid
, const void *shmaddr
, int shmflg
) {
1132 ENSURE_MSAN_INITED();
1133 void *p
= REAL(shmat
)(shmid
, shmaddr
, shmflg
);
1134 if (p
!= (void *)-1) {
1135 __sanitizer_shmid_ds ds
;
1136 int res
= REAL(shmctl
)(shmid
, shmctl_ipc_stat
, &ds
);
1138 __msan_unpoison(p
, ds
.shm_segsz
);
1144 // Linux kernel has a bug that leads to kernel deadlock if a process
1145 // maps TBs of memory and then calls mlock().
1146 static void MlockIsUnsupported() {
1147 static atomic_uint8_t printed
;
1148 if (atomic_exchange(&printed
, 1, memory_order_relaxed
))
1151 "INFO: MemorySanitizer ignores mlock/mlockall/munlock/munlockall\n");
1154 INTERCEPTOR(int, mlock
, const void *addr
, uptr len
) {
1155 MlockIsUnsupported();
1159 INTERCEPTOR(int, munlock
, const void *addr
, uptr len
) {
1160 MlockIsUnsupported();
1164 INTERCEPTOR(int, mlockall
, int flags
) {
1165 MlockIsUnsupported();
1169 INTERCEPTOR(int, munlockall
, void) {
1170 MlockIsUnsupported();
1174 struct MSanInterceptorContext
{
1175 bool in_interceptor_scope
;
1181 // FIXME: ask frontend whether we need to return failure.
1185 } // namespace __msan
1187 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1189 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1191 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1192 CHECK_UNPOISONED_0(x, n); \
1195 #define MSAN_INTERCEPT_FUNC(name) \
1197 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
1198 VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \
1201 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1202 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1203 UnpoisonParam(count)
1204 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1205 __msan_unpoison(ptr, size)
1206 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1207 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1208 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1209 __msan_unpoison(ptr, size)
1210 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1211 if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \
1212 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1213 ctx = (void *)&msan_ctx; \
1215 InterceptorScope interceptor_scope; \
1216 __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ \
1217 ENSURE_MSAN_INITED();
1218 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1221 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1224 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1227 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1229 } while (false) // FIXME
1230 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1232 } while (false) // FIXME
1233 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1234 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1235 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1237 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1238 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1241 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1244 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1245 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1248 void *fast_memset(void *ptr
, int c
, SIZE_T n
) {
1249 // hack until we have a really fast internal_memset
1250 if (sizeof(uptr
) == 8 &&
1252 ((uptr
)ptr
% 8) == 0 &&
1253 (c
== 0 || c
== -1)) {
1254 // Printf("memset %p %zd %x\n", ptr, n, c);
1255 uptr to_store
= c
? -1L : 0L;
1256 uptr
*p
= (uptr
*)ptr
;
1257 for (SIZE_T i
= 0; i
< n
/ 8; i
++)
1261 return internal_memset(ptr
, c
, n
);
1265 void *fast_memcpy(void *dst
, const void *src
, SIZE_T n
) {
1266 // Same hack as in fast_memset above.
1267 if (sizeof(uptr
) == 8 &&
1269 ((uptr
)dst
% 8) == 0 &&
1270 ((uptr
)src
% 8) == 0) {
1271 uptr
*d
= (uptr
*)dst
;
1272 uptr
*s
= (uptr
*)src
;
1273 for (SIZE_T i
= 0; i
< n
/ 8; i
++)
1277 return internal_memcpy(dst
, src
, n
);
1280 static void PoisonShadow(uptr ptr
, uptr size
, u8 value
) {
1281 uptr PageSize
= GetPageSizeCached();
1282 uptr shadow_beg
= MEM_TO_SHADOW(ptr
);
1283 uptr shadow_end
= MEM_TO_SHADOW(ptr
+ size
);
1285 shadow_end
- shadow_beg
< common_flags()->clear_shadow_mmap_threshold
) {
1286 fast_memset((void*)shadow_beg
, value
, shadow_end
- shadow_beg
);
1288 uptr page_beg
= RoundUpTo(shadow_beg
, PageSize
);
1289 uptr page_end
= RoundDownTo(shadow_end
, PageSize
);
1291 if (page_beg
>= page_end
) {
1292 fast_memset((void *)shadow_beg
, 0, shadow_end
- shadow_beg
);
1294 if (page_beg
!= shadow_beg
) {
1295 fast_memset((void *)shadow_beg
, 0, page_beg
- shadow_beg
);
1297 if (page_end
!= shadow_end
) {
1298 fast_memset((void *)page_end
, 0, shadow_end
- page_end
);
1300 MmapFixedNoReserve(page_beg
, page_end
- page_beg
);
1305 // These interface functions reside here so that they can use
1306 // fast_memset, etc.
1307 void __msan_unpoison(const void *a
, uptr size
) {
1308 if (!MEM_IS_APP(a
)) return;
1309 PoisonShadow((uptr
)a
, size
, 0);
1312 void __msan_poison(const void *a
, uptr size
) {
1313 if (!MEM_IS_APP(a
)) return;
1314 PoisonShadow((uptr
)a
, size
,
1315 __msan::flags()->poison_heap_with_zeroes
? 0 : -1);
1318 void __msan_poison_stack(void *a
, uptr size
) {
1319 if (!MEM_IS_APP(a
)) return;
1320 PoisonShadow((uptr
)a
, size
,
1321 __msan::flags()->poison_stack_with_zeroes
? 0 : -1);
1324 void __msan_clear_and_unpoison(void *a
, uptr size
) {
1325 fast_memset(a
, 0, size
);
1326 PoisonShadow((uptr
)a
, size
, 0);
1329 void *__msan_memcpy(void *dest
, const void *src
, SIZE_T n
) {
1330 if (!msan_inited
) return internal_memcpy(dest
, src
, n
);
1331 if (msan_init_is_running
) return REAL(memcpy
)(dest
, src
, n
);
1332 ENSURE_MSAN_INITED();
1333 GET_STORE_STACK_TRACE
;
1334 void *res
= fast_memcpy(dest
, src
, n
);
1335 CopyPoison(dest
, src
, n
, &stack
);
1339 void *__msan_memset(void *s
, int c
, SIZE_T n
) {
1340 if (!msan_inited
) return internal_memset(s
, c
, n
);
1341 if (msan_init_is_running
) return REAL(memset
)(s
, c
, n
);
1342 ENSURE_MSAN_INITED();
1343 void *res
= fast_memset(s
, c
, n
);
1344 __msan_unpoison(s
, n
);
1348 void *__msan_memmove(void *dest
, const void *src
, SIZE_T n
) {
1349 if (!msan_inited
) return internal_memmove(dest
, src
, n
);
1350 if (msan_init_is_running
) return REAL(memmove
)(dest
, src
, n
);
1351 ENSURE_MSAN_INITED();
1352 GET_STORE_STACK_TRACE
;
1353 void *res
= REAL(memmove
)(dest
, src
, n
);
1354 MovePoison(dest
, src
, n
, &stack
);
1358 void __msan_unpoison_string(const char* s
) {
1359 if (!MEM_IS_APP(s
)) return;
1360 __msan_unpoison(s
, REAL(strlen
)(s
) + 1);
1365 u32
GetOriginIfPoisoned(uptr addr
, uptr size
) {
1366 unsigned char *s
= (unsigned char *)MEM_TO_SHADOW(addr
);
1367 for (uptr i
= 0; i
< size
; ++i
)
1369 return *(u32
*)SHADOW_TO_ORIGIN((s
+ i
) & ~3UL);
1373 void SetOriginIfPoisoned(uptr addr
, uptr src_shadow
, uptr size
,
1375 uptr dst_s
= MEM_TO_SHADOW(addr
);
1376 uptr src_s
= src_shadow
;
1377 uptr src_s_end
= src_s
+ size
;
1379 for (; src_s
< src_s_end
; ++dst_s
, ++src_s
)
1380 if (*(u8
*)src_s
) *(u32
*)SHADOW_TO_ORIGIN(dst_s
&~3UL) = src_origin
;
1383 void CopyOrigin(void *dst
, const void *src
, uptr size
, StackTrace
*stack
) {
1384 if (!__msan_get_track_origins()) return;
1385 if (!MEM_IS_APP(dst
) || !MEM_IS_APP(src
)) return;
1388 uptr beg
= d
& ~3UL;
1389 // Copy left unaligned origin if that memory is poisoned.
1391 u32 o
= GetOriginIfPoisoned(beg
, d
- beg
);
1393 if (__msan_get_track_origins() > 1) o
= ChainOrigin(o
, stack
);
1394 *(u32
*)MEM_TO_ORIGIN(beg
) = o
;
1399 uptr end
= (d
+ size
+ 3) & ~3UL;
1400 // Copy right unaligned origin if that memory is poisoned.
1401 if (end
> d
+ size
) {
1402 u32 o
= GetOriginIfPoisoned(d
+ size
, end
- d
- size
);
1404 if (__msan_get_track_origins() > 1) o
= ChainOrigin(o
, stack
);
1405 *(u32
*)MEM_TO_ORIGIN(end
- 4) = o
;
1412 uptr s
= ((uptr
)src
+ 3) & ~3UL;
1413 // FIXME: factor out to msan_copy_origin_aligned
1414 if (__msan_get_track_origins() > 1) {
1415 u32
*src
= (u32
*)MEM_TO_ORIGIN(s
);
1416 u32
*src_s
= (u32
*)MEM_TO_SHADOW(s
);
1417 u32
*src_end
= src
+ (end
- beg
);
1418 u32
*dst
= (u32
*)MEM_TO_ORIGIN(beg
);
1421 for (; src
< src_end
; ++src
, ++src_s
, ++dst
) {
1422 if (!*src_s
) continue;
1423 if (*src
!= src_o
) {
1425 dst_o
= ChainOrigin(src_o
, stack
);
1430 fast_memcpy((void *)MEM_TO_ORIGIN(beg
), (void *)MEM_TO_ORIGIN(s
),
1436 void MovePoison(void *dst
, const void *src
, uptr size
, StackTrace
*stack
) {
1437 if (!MEM_IS_APP(dst
)) return;
1438 if (!MEM_IS_APP(src
)) return;
1439 if (src
== dst
) return;
1440 internal_memmove((void *)MEM_TO_SHADOW((uptr
)dst
),
1441 (void *)MEM_TO_SHADOW((uptr
)src
), size
);
1442 CopyOrigin(dst
, src
, size
, stack
);
1445 void CopyPoison(void *dst
, const void *src
, uptr size
, StackTrace
*stack
) {
1446 if (!MEM_IS_APP(dst
)) return;
1447 if (!MEM_IS_APP(src
)) return;
1448 fast_memcpy((void *)MEM_TO_SHADOW((uptr
)dst
),
1449 (void *)MEM_TO_SHADOW((uptr
)src
), size
);
1450 CopyOrigin(dst
, src
, size
, stack
);
1453 void InitializeInterceptors() {
1454 static int inited
= 0;
1455 CHECK_EQ(inited
, 0);
1456 InitializeCommonInterceptors();
1458 INTERCEPT_FUNCTION(mmap
);
1459 INTERCEPT_FUNCTION(mmap64
);
1460 INTERCEPT_FUNCTION(posix_memalign
);
1461 INTERCEPT_FUNCTION(memalign
);
1462 INTERCEPT_FUNCTION(valloc
);
1463 INTERCEPT_FUNCTION(pvalloc
);
1464 INTERCEPT_FUNCTION(malloc
);
1465 INTERCEPT_FUNCTION(calloc
);
1466 INTERCEPT_FUNCTION(realloc
);
1467 INTERCEPT_FUNCTION(free
);
1468 INTERCEPT_FUNCTION(cfree
);
1469 INTERCEPT_FUNCTION(malloc_usable_size
);
1470 INTERCEPT_FUNCTION(mallinfo
);
1471 INTERCEPT_FUNCTION(mallopt
);
1472 INTERCEPT_FUNCTION(malloc_stats
);
1473 INTERCEPT_FUNCTION(fread
);
1474 INTERCEPT_FUNCTION(fread_unlocked
);
1475 INTERCEPT_FUNCTION(readlink
);
1476 INTERCEPT_FUNCTION(memcpy
);
1477 INTERCEPT_FUNCTION(memccpy
);
1478 INTERCEPT_FUNCTION(mempcpy
);
1479 INTERCEPT_FUNCTION(memset
);
1480 INTERCEPT_FUNCTION(memmove
);
1481 INTERCEPT_FUNCTION(bcopy
);
1482 INTERCEPT_FUNCTION(wmemset
);
1483 INTERCEPT_FUNCTION(wmemcpy
);
1484 INTERCEPT_FUNCTION(wmempcpy
);
1485 INTERCEPT_FUNCTION(wmemmove
);
1486 INTERCEPT_FUNCTION(strcpy
); // NOLINT
1487 INTERCEPT_FUNCTION(stpcpy
); // NOLINT
1488 INTERCEPT_FUNCTION(strdup
);
1489 INTERCEPT_FUNCTION(__strdup
);
1490 INTERCEPT_FUNCTION(strndup
);
1491 INTERCEPT_FUNCTION(__strndup
);
1492 INTERCEPT_FUNCTION(strncpy
); // NOLINT
1493 INTERCEPT_FUNCTION(strlen
);
1494 INTERCEPT_FUNCTION(strnlen
);
1495 INTERCEPT_FUNCTION(gcvt
);
1496 INTERCEPT_FUNCTION(strcat
); // NOLINT
1497 INTERCEPT_FUNCTION(strncat
); // NOLINT
1498 INTERCEPT_FUNCTION(strtol
);
1499 INTERCEPT_FUNCTION(strtoll
);
1500 INTERCEPT_FUNCTION(strtoul
);
1501 INTERCEPT_FUNCTION(strtoull
);
1502 INTERCEPT_FUNCTION(strtod
);
1503 INTERCEPT_FUNCTION(strtod_l
);
1504 INTERCEPT_FUNCTION(__strtod_l
);
1505 INTERCEPT_FUNCTION(strtof
);
1506 INTERCEPT_FUNCTION(strtof_l
);
1507 INTERCEPT_FUNCTION(__strtof_l
);
1508 INTERCEPT_FUNCTION(strtold
);
1509 INTERCEPT_FUNCTION(strtold_l
);
1510 INTERCEPT_FUNCTION(__strtold_l
);
1511 INTERCEPT_FUNCTION(strtol_l
);
1512 INTERCEPT_FUNCTION(strtoll_l
);
1513 INTERCEPT_FUNCTION(strtoul_l
);
1514 INTERCEPT_FUNCTION(strtoull_l
);
1515 INTERCEPT_FUNCTION(vswprintf
);
1516 INTERCEPT_FUNCTION(swprintf
);
1517 INTERCEPT_FUNCTION(strxfrm
);
1518 INTERCEPT_FUNCTION(strxfrm_l
);
1519 INTERCEPT_FUNCTION(strftime
);
1520 INTERCEPT_FUNCTION(strftime_l
);
1521 INTERCEPT_FUNCTION(__strftime_l
);
1522 INTERCEPT_FUNCTION(wcsftime
);
1523 INTERCEPT_FUNCTION(wcsftime_l
);
1524 INTERCEPT_FUNCTION(__wcsftime_l
);
1525 INTERCEPT_FUNCTION(mbtowc
);
1526 INTERCEPT_FUNCTION(mbrtowc
);
1527 INTERCEPT_FUNCTION(wcslen
);
1528 INTERCEPT_FUNCTION(wcschr
);
1529 INTERCEPT_FUNCTION(wcscpy
);
1530 INTERCEPT_FUNCTION(wcscmp
);
1531 INTERCEPT_FUNCTION(wcstod
);
1532 INTERCEPT_FUNCTION(getenv
);
1533 INTERCEPT_FUNCTION(setenv
);
1534 INTERCEPT_FUNCTION(putenv
);
1535 INTERCEPT_FUNCTION(gettimeofday
);
1536 INTERCEPT_FUNCTION(fcvt
);
1537 INTERCEPT_FUNCTION(__fxstat
);
1538 INTERCEPT_FUNCTION(__fxstatat
);
1539 INTERCEPT_FUNCTION(__xstat
);
1540 INTERCEPT_FUNCTION(__lxstat
);
1541 INTERCEPT_FUNCTION(__fxstat64
);
1542 INTERCEPT_FUNCTION(__fxstatat64
);
1543 INTERCEPT_FUNCTION(__xstat64
);
1544 INTERCEPT_FUNCTION(__lxstat64
);
1545 INTERCEPT_FUNCTION(pipe
);
1546 INTERCEPT_FUNCTION(pipe2
);
1547 INTERCEPT_FUNCTION(socketpair
);
1548 INTERCEPT_FUNCTION(fgets
);
1549 INTERCEPT_FUNCTION(fgets_unlocked
);
1550 INTERCEPT_FUNCTION(getrlimit
);
1551 INTERCEPT_FUNCTION(getrlimit64
);
1552 INTERCEPT_FUNCTION(uname
);
1553 INTERCEPT_FUNCTION(gethostname
);
1554 INTERCEPT_FUNCTION(epoll_wait
);
1555 INTERCEPT_FUNCTION(epoll_pwait
);
1556 INTERCEPT_FUNCTION(recv
);
1557 INTERCEPT_FUNCTION(recvfrom
);
1558 INTERCEPT_FUNCTION(dladdr
);
1559 INTERCEPT_FUNCTION(dlerror
);
1560 INTERCEPT_FUNCTION(dlopen
);
1561 INTERCEPT_FUNCTION(dl_iterate_phdr
);
1562 INTERCEPT_FUNCTION(getrusage
);
1563 INTERCEPT_FUNCTION(sigaction
);
1564 INTERCEPT_FUNCTION(signal
);
1565 INTERCEPT_FUNCTION(pthread_create
);
1566 INTERCEPT_FUNCTION(pthread_key_create
);
1567 INTERCEPT_FUNCTION(pthread_join
);
1568 INTERCEPT_FUNCTION(tzset
);
1569 INTERCEPT_FUNCTION(__cxa_atexit
);
1570 INTERCEPT_FUNCTION(shmat
);
1574 } // namespace __msan