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