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