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