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