1 //===-- msan_interceptors.cc ----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of MemorySanitizer. 11 // 12 // Interceptors for standard library functions. 13 // 14 // FIXME: move as many interceptors as possible into 15 // sanitizer_common/sanitizer_common_interceptors.h 16 //===----------------------------------------------------------------------===// 17 18 #include "msan.h" 19 #include "msan_chained_origin_depot.h" 20 #include "msan_origin.h" 21 #include "msan_thread.h" 22 #include "sanitizer_common/sanitizer_platform_limits_posix.h" 23 #include "sanitizer_common/sanitizer_allocator.h" 24 #include "sanitizer_common/sanitizer_allocator_interface.h" 25 #include "sanitizer_common/sanitizer_allocator_internal.h" 26 #include "sanitizer_common/sanitizer_atomic.h" 27 #include "sanitizer_common/sanitizer_common.h" 28 #include "sanitizer_common/sanitizer_interception.h" 29 #include "sanitizer_common/sanitizer_stackdepot.h" 30 #include "sanitizer_common/sanitizer_libc.h" 31 #include "sanitizer_common/sanitizer_linux.h" 32 #include "sanitizer_common/sanitizer_tls_get_addr.h" 33 34 #include <stdarg.h> 35 // ACHTUNG! No other system header includes in this file. 36 // Ideally, we should get rid of stdarg.h as well. 37 38 using namespace __msan; 39 40 using __sanitizer::memory_order; 41 using __sanitizer::atomic_load; 42 using __sanitizer::atomic_store; 43 using __sanitizer::atomic_uintptr_t; 44 45 // True if this is a nested interceptor. 46 static THREADLOCAL int in_interceptor_scope; 47 48 extern "C" int *__errno_location(void); 49 50 struct InterceptorScope { 51 InterceptorScope() { ++in_interceptor_scope; } 52 ~InterceptorScope() { --in_interceptor_scope; } 53 }; 54 55 bool IsInInterceptorScope() { 56 return in_interceptor_scope; 57 } 58 59 #define ENSURE_MSAN_INITED() do { \ 60 CHECK(!msan_init_is_running); \ 61 if (!msan_inited) { \ 62 __msan_init(); \ 63 } \ 64 } while (0) 65 66 // Check that [x, x+n) range is unpoisoned. 67 #define CHECK_UNPOISONED_0(x, n) \ 68 do { \ 69 sptr offset = __msan_test_shadow(x, n); \ 70 if (__msan::IsInSymbolizer()) break; \ 71 if (offset >= 0 && __msan::flags()->report_umrs) { \ 72 GET_CALLER_PC_BP_SP; \ 73 (void) sp; \ 74 ReportUMRInsideAddressRange(__func__, x, n, offset); \ 75 __msan::PrintWarningWithOrigin(pc, bp, \ 76 __msan_get_origin((char *)x + offset)); \ 77 if (__msan::flags()->halt_on_error) { \ 78 Printf("Exiting\n"); \ 79 Die(); \ 80 } \ 81 } \ 82 } while (0) 83 84 // Check that [x, x+n) range is unpoisoned unless we are in a nested 85 // interceptor. 86 #define CHECK_UNPOISONED(x, n) \ 87 do { \ 88 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \ 89 } while (0); 90 91 static void *fast_memset(void *ptr, int c, SIZE_T n); 92 static void *fast_memcpy(void *dst, const void *src, SIZE_T n); 93 94 INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) { 95 ENSURE_MSAN_INITED(); 96 SIZE_T res = REAL(fread)(ptr, size, nmemb, file); 97 if (res > 0) 98 __msan_unpoison(ptr, res *size); 99 return res; 100 } 101 102 INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb, 103 void *file) { 104 ENSURE_MSAN_INITED(); 105 SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file); 106 if (res > 0) 107 __msan_unpoison(ptr, res *size); 108 return res; 109 } 110 111 INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) { 112 ENSURE_MSAN_INITED(); 113 SSIZE_T res = REAL(readlink)(path, buf, bufsiz); 114 if (res > 0) 115 __msan_unpoison(buf, res); 116 return res; 117 } 118 119 INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) { 120 return __msan_memcpy(dest, src, n); 121 } 122 123 INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) { 124 return (char *)__msan_memcpy(dest, src, n) + n; 125 } 126 127 INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) { 128 ENSURE_MSAN_INITED(); 129 void *res = REAL(memccpy)(dest, src, c, n); 130 CHECK(!res || (res >= dest && res <= (char *)dest + n)); 131 SIZE_T sz = res ? (char *)res - (char *)dest : n; 132 CHECK_UNPOISONED(src, sz); 133 __msan_unpoison(dest, sz); 134 return res; 135 } 136 137 INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) { 138 return __msan_memmove(dest, src, n); 139 } 140 141 INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) { 142 return __msan_memset(s, c, n); 143 } 144 145 INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) { 146 return __msan_memmove(dest, src, n); 147 } 148 149 INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) { 150 GET_MALLOC_STACK_TRACE; 151 CHECK_EQ(alignment & (alignment - 1), 0); 152 CHECK_NE(memptr, 0); 153 *memptr = MsanReallocate(&stack, 0, size, alignment, false); 154 CHECK_NE(*memptr, 0); 155 __msan_unpoison(memptr, sizeof(*memptr)); 156 return 0; 157 } 158 159 INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) { 160 GET_MALLOC_STACK_TRACE; 161 CHECK_EQ(boundary & (boundary - 1), 0); 162 void *ptr = MsanReallocate(&stack, 0, size, boundary, false); 163 return ptr; 164 } 165 166 INTERCEPTOR(void *, aligned_alloc, SIZE_T boundary, SIZE_T size) { 167 GET_MALLOC_STACK_TRACE; 168 CHECK_EQ(boundary & (boundary - 1), 0); 169 void *ptr = MsanReallocate(&stack, 0, size, boundary, false); 170 return ptr; 171 } 172 173 INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) { 174 GET_MALLOC_STACK_TRACE; 175 CHECK_EQ(boundary & (boundary - 1), 0); 176 void *ptr = MsanReallocate(&stack, 0, size, boundary, false); 177 DTLS_on_libc_memalign(ptr, size * boundary); 178 return ptr; 179 } 180 181 INTERCEPTOR(void *, valloc, SIZE_T size) { 182 GET_MALLOC_STACK_TRACE; 183 void *ptr = MsanReallocate(&stack, 0, size, GetPageSizeCached(), false); 184 return ptr; 185 } 186 187 INTERCEPTOR(void *, pvalloc, SIZE_T size) { 188 GET_MALLOC_STACK_TRACE; 189 uptr PageSize = GetPageSizeCached(); 190 size = RoundUpTo(size, PageSize); 191 if (size == 0) { 192 // pvalloc(0) should allocate one page. 193 size = PageSize; 194 } 195 void *ptr = MsanReallocate(&stack, 0, size, PageSize, false); 196 return ptr; 197 } 198 199 INTERCEPTOR(void, free, void *ptr) { 200 GET_MALLOC_STACK_TRACE; 201 if (ptr == 0) return; 202 MsanDeallocate(&stack, ptr); 203 } 204 205 INTERCEPTOR(void, cfree, void *ptr) { 206 GET_MALLOC_STACK_TRACE; 207 if (ptr == 0) return; 208 MsanDeallocate(&stack, ptr); 209 } 210 211 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 212 return __sanitizer_get_allocated_size(ptr); 213 } 214 215 // This function actually returns a struct by value, but we can't unpoison a 216 // temporary! The following is equivalent on all supported platforms, and we 217 // have a test to confirm that. 218 INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) { 219 REAL(memset)(sret, 0, sizeof(*sret)); 220 __msan_unpoison(sret, sizeof(*sret)); 221 } 222 223 INTERCEPTOR(int, mallopt, int cmd, int value) { 224 return -1; 225 } 226 227 INTERCEPTOR(void, malloc_stats, void) { 228 // FIXME: implement, but don't call REAL(malloc_stats)! 229 } 230 231 INTERCEPTOR(SIZE_T, strlen, const char *s) { 232 ENSURE_MSAN_INITED(); 233 SIZE_T res = REAL(strlen)(s); 234 CHECK_UNPOISONED(s, res + 1); 235 return res; 236 } 237 238 INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) { 239 ENSURE_MSAN_INITED(); 240 SIZE_T res = REAL(strnlen)(s, n); 241 SIZE_T scan_size = (res == n) ? res : res + 1; 242 CHECK_UNPOISONED(s, scan_size); 243 return res; 244 } 245 246 // FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should 247 // check the shadow of the terminating \0 byte). 248 249 INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT 250 ENSURE_MSAN_INITED(); 251 GET_STORE_STACK_TRACE; 252 SIZE_T n = REAL(strlen)(src); 253 char *res = REAL(strcpy)(dest, src); // NOLINT 254 CopyPoison(dest, src, n + 1, &stack); 255 return res; 256 } 257 258 INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT 259 ENSURE_MSAN_INITED(); 260 GET_STORE_STACK_TRACE; 261 SIZE_T copy_size = REAL(strnlen)(src, n); 262 if (copy_size < n) 263 copy_size++; // trailing \0 264 char *res = REAL(strncpy)(dest, src, n); // NOLINT 265 CopyPoison(dest, src, copy_size, &stack); 266 return res; 267 } 268 269 INTERCEPTOR(char *, stpcpy, char *dest, const char *src) { // NOLINT 270 ENSURE_MSAN_INITED(); 271 GET_STORE_STACK_TRACE; 272 SIZE_T n = REAL(strlen)(src); 273 char *res = REAL(stpcpy)(dest, src); // NOLINT 274 CopyPoison(dest, src, n + 1, &stack); 275 return res; 276 } 277 278 INTERCEPTOR(char *, strdup, char *src) { 279 ENSURE_MSAN_INITED(); 280 GET_STORE_STACK_TRACE; 281 SIZE_T n = REAL(strlen)(src); 282 char *res = REAL(strdup)(src); 283 CopyPoison(res, src, n + 1, &stack); 284 return res; 285 } 286 287 INTERCEPTOR(char *, __strdup, char *src) { 288 ENSURE_MSAN_INITED(); 289 GET_STORE_STACK_TRACE; 290 SIZE_T n = REAL(strlen)(src); 291 char *res = REAL(__strdup)(src); 292 CopyPoison(res, src, n + 1, &stack); 293 return res; 294 } 295 296 INTERCEPTOR(char *, strndup, char *src, SIZE_T n) { 297 ENSURE_MSAN_INITED(); 298 GET_STORE_STACK_TRACE; 299 SIZE_T copy_size = REAL(strnlen)(src, n); 300 char *res = REAL(strndup)(src, n); 301 CopyPoison(res, src, copy_size, &stack); 302 __msan_unpoison(res + copy_size, 1); // \0 303 return res; 304 } 305 306 INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) { 307 ENSURE_MSAN_INITED(); 308 GET_STORE_STACK_TRACE; 309 SIZE_T copy_size = REAL(strnlen)(src, n); 310 char *res = REAL(__strndup)(src, n); 311 CopyPoison(res, src, copy_size, &stack); 312 __msan_unpoison(res + copy_size, 1); // \0 313 return res; 314 } 315 316 INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { 317 ENSURE_MSAN_INITED(); 318 char *res = REAL(gcvt)(number, ndigit, buf); 319 // DynamoRio tool will take care of unpoisoning gcvt result for us. 320 if (!__msan_has_dynamic_component()) { 321 SIZE_T n = REAL(strlen)(buf); 322 __msan_unpoison(buf, n + 1); 323 } 324 return res; 325 } 326 327 INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT 328 ENSURE_MSAN_INITED(); 329 GET_STORE_STACK_TRACE; 330 SIZE_T src_size = REAL(strlen)(src); 331 SIZE_T dest_size = REAL(strlen)(dest); 332 char *res = REAL(strcat)(dest, src); // NOLINT 333 CopyPoison(dest + dest_size, src, src_size + 1, &stack); 334 return res; 335 } 336 337 INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT 338 ENSURE_MSAN_INITED(); 339 GET_STORE_STACK_TRACE; 340 SIZE_T dest_size = REAL(strlen)(dest); 341 SIZE_T copy_size = REAL(strnlen)(src, n); 342 char *res = REAL(strncat)(dest, src, n); // NOLINT 343 CopyPoison(dest + dest_size, src, copy_size, &stack); 344 __msan_unpoison(dest + dest_size + copy_size, 1); // \0 345 return res; 346 } 347 348 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to 349 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO. 350 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \ 351 ENSURE_MSAN_INITED(); \ 352 ret_type res = REAL(func)(__VA_ARGS__); \ 353 if (!__msan_has_dynamic_component()) { \ 354 __msan_unpoison(endptr, sizeof(*endptr)); \ 355 } \ 356 return res; 357 358 #define INTERCEPTOR_STRTO(ret_type, func) \ 359 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr) { \ 360 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \ 361 } 362 363 #define INTERCEPTOR_STRTO_BASE(ret_type, func) \ 364 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \ 365 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \ 366 } 367 368 #define INTERCEPTOR_STRTO_LOC(ret_type, func) \ 369 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, void *loc) { \ 370 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \ 371 } 372 373 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func) \ 374 INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base, \ 375 void *loc) { \ 376 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \ 377 } 378 379 INTERCEPTOR_STRTO(double, strtod) // NOLINT 380 INTERCEPTOR_STRTO(float, strtof) // NOLINT 381 INTERCEPTOR_STRTO(long double, strtold) // NOLINT 382 INTERCEPTOR_STRTO_BASE(long, strtol) // NOLINT 383 INTERCEPTOR_STRTO_BASE(long long, strtoll) // NOLINT 384 INTERCEPTOR_STRTO_BASE(unsigned long, strtoul) // NOLINT 385 INTERCEPTOR_STRTO_BASE(unsigned long long, strtoull) // NOLINT 386 INTERCEPTOR_STRTO_LOC(double, strtod_l) // NOLINT 387 INTERCEPTOR_STRTO_LOC(double, __strtod_l) // NOLINT 388 INTERCEPTOR_STRTO_LOC(double, __strtod_internal) // NOLINT 389 INTERCEPTOR_STRTO_LOC(float, strtof_l) // NOLINT 390 INTERCEPTOR_STRTO_LOC(float, __strtof_l) // NOLINT 391 INTERCEPTOR_STRTO_LOC(float, __strtof_internal) // NOLINT 392 INTERCEPTOR_STRTO_LOC(long double, strtold_l) // NOLINT 393 INTERCEPTOR_STRTO_LOC(long double, __strtold_l) // NOLINT 394 INTERCEPTOR_STRTO_LOC(long double, __strtold_internal) // NOLINT 395 INTERCEPTOR_STRTO_BASE_LOC(long, strtol_l) // NOLINT 396 INTERCEPTOR_STRTO_BASE_LOC(long, __strtol_l) // NOLINT 397 INTERCEPTOR_STRTO_BASE_LOC(long, __strtol_internal) // NOLINT 398 INTERCEPTOR_STRTO_BASE_LOC(long long, strtoll_l) // NOLINT 399 INTERCEPTOR_STRTO_BASE_LOC(long long, __strtoll_l) // NOLINT 400 INTERCEPTOR_STRTO_BASE_LOC(long long, __strtoll_internal) // NOLINT 401 INTERCEPTOR_STRTO_BASE_LOC(unsigned long, strtoul_l) // NOLINT 402 INTERCEPTOR_STRTO_BASE_LOC(unsigned long, __strtoul_l) // NOLINT 403 INTERCEPTOR_STRTO_BASE_LOC(unsigned long, __strtoul_internal) // NOLINT 404 INTERCEPTOR_STRTO_BASE_LOC(unsigned long long, strtoull_l) // NOLINT 405 INTERCEPTOR_STRTO_BASE_LOC(unsigned long long, __strtoull_l) // NOLINT 406 INTERCEPTOR_STRTO_BASE_LOC(unsigned long long, __strtoull_internal) // NOLINT 407 408 // FIXME: support *wprintf in common format interceptors. 409 INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) { 410 ENSURE_MSAN_INITED(); 411 int res = REAL(vswprintf)(str, size, format, ap); 412 if (res >= 0 && !__msan_has_dynamic_component()) { 413 __msan_unpoison(str, 4 * (res + 1)); 414 } 415 return res; 416 } 417 418 INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) { 419 ENSURE_MSAN_INITED(); 420 va_list ap; 421 va_start(ap, format); 422 int res = vswprintf(str, size, format, ap); 423 va_end(ap); 424 return res; 425 } 426 427 INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T n) { 428 ENSURE_MSAN_INITED(); 429 CHECK_UNPOISONED(src, REAL(strlen)(src) + 1); 430 SIZE_T res = REAL(strxfrm)(dest, src, n); 431 if (res < n) __msan_unpoison(dest, res + 1); 432 return res; 433 } 434 435 INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T n, 436 void *loc) { 437 ENSURE_MSAN_INITED(); 438 CHECK_UNPOISONED(src, REAL(strlen)(src) + 1); 439 SIZE_T res = REAL(strxfrm_l)(dest, src, n, loc); 440 if (res < n) __msan_unpoison(dest, res + 1); 441 return res; 442 } 443 444 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \ 445 ENSURE_MSAN_INITED(); \ 446 ret_type res = REAL(func)(s, __VA_ARGS__); \ 447 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \ 448 return res; 449 450 INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format, 451 __sanitizer_tm *tm) { 452 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm); 453 } 454 455 INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format, 456 __sanitizer_tm *tm, void *loc) { 457 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc); 458 } 459 460 INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format, 461 __sanitizer_tm *tm, void *loc) { 462 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm, 463 loc); 464 } 465 466 INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format, 467 __sanitizer_tm *tm) { 468 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm); 469 } 470 471 INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format, 472 __sanitizer_tm *tm, void *loc) { 473 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm, 474 loc); 475 } 476 477 INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format, 478 __sanitizer_tm *tm, void *loc) { 479 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm, 480 loc); 481 } 482 483 INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) { 484 ENSURE_MSAN_INITED(); 485 int res = REAL(mbtowc)(dest, src, n); 486 if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 487 return res; 488 } 489 490 INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) { 491 ENSURE_MSAN_INITED(); 492 SIZE_T res = REAL(mbrtowc)(dest, src, n, ps); 493 if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 494 return res; 495 } 496 497 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { 498 ENSURE_MSAN_INITED(); 499 SIZE_T res = REAL(wcslen)(s); 500 CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1)); 501 return res; 502 } 503 504 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); 505 INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { 506 ENSURE_MSAN_INITED(); 507 wchar_t *res = REAL(wcschr)(s, wc, ps); 508 return res; 509 } 510 511 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); 512 INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { 513 ENSURE_MSAN_INITED(); 514 GET_STORE_STACK_TRACE; 515 wchar_t *res = REAL(wcscpy)(dest, src); 516 CopyPoison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1), &stack); 517 return res; 518 } 519 520 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n); 521 INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 522 ENSURE_MSAN_INITED(); 523 GET_STORE_STACK_TRACE; 524 wchar_t *res = REAL(wmemcpy)(dest, src, n); 525 CopyPoison(dest, src, n * sizeof(wchar_t), &stack); 526 return res; 527 } 528 529 INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 530 ENSURE_MSAN_INITED(); 531 GET_STORE_STACK_TRACE; 532 wchar_t *res = REAL(wmempcpy)(dest, src, n); 533 CopyPoison(dest, src, n * sizeof(wchar_t), &stack); 534 return res; 535 } 536 537 INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) { 538 CHECK(MEM_IS_APP(s)); 539 ENSURE_MSAN_INITED(); 540 wchar_t *res = (wchar_t *)fast_memset(s, c, n * sizeof(wchar_t)); 541 __msan_unpoison(s, n * sizeof(wchar_t)); 542 return res; 543 } 544 545 INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) { 546 ENSURE_MSAN_INITED(); 547 GET_STORE_STACK_TRACE; 548 wchar_t *res = REAL(wmemmove)(dest, src, n); 549 MovePoison(dest, src, n * sizeof(wchar_t), &stack); 550 return res; 551 } 552 553 INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) { 554 ENSURE_MSAN_INITED(); 555 int res = REAL(wcscmp)(s1, s2); 556 return res; 557 } 558 559 INTERCEPTOR(double, wcstod, const wchar_t *nptr, wchar_t **endptr) { 560 ENSURE_MSAN_INITED(); 561 double res = REAL(wcstod)(nptr, endptr); 562 __msan_unpoison(endptr, sizeof(*endptr)); 563 return res; 564 } 565 566 INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { 567 ENSURE_MSAN_INITED(); 568 int res = REAL(gettimeofday)(tv, tz); 569 if (tv) 570 __msan_unpoison(tv, 16); 571 if (tz) 572 __msan_unpoison(tz, 8); 573 return res; 574 } 575 576 INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) { 577 ENSURE_MSAN_INITED(); 578 char *res = REAL(fcvt)(x, a, b, c); 579 if (!__msan_has_dynamic_component()) { 580 __msan_unpoison(b, sizeof(*b)); 581 __msan_unpoison(c, sizeof(*c)); 582 } 583 return res; 584 } 585 586 INTERCEPTOR(char *, getenv, char *name) { 587 ENSURE_MSAN_INITED(); 588 char *res = REAL(getenv)(name); 589 if (!__msan_has_dynamic_component()) { 590 if (res) 591 __msan_unpoison(res, REAL(strlen)(res) + 1); 592 } 593 return res; 594 } 595 596 extern char **environ; 597 598 static void UnpoisonEnviron() { 599 char **envp = environ; 600 for (; *envp; ++envp) { 601 __msan_unpoison(envp, sizeof(*envp)); 602 __msan_unpoison(*envp, REAL(strlen)(*envp) + 1); 603 } 604 // Trailing NULL pointer. 605 __msan_unpoison(envp, sizeof(*envp)); 606 } 607 608 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) { 609 ENSURE_MSAN_INITED(); 610 int res = REAL(setenv)(name, value, overwrite); 611 if (!res) UnpoisonEnviron(); 612 return res; 613 } 614 615 INTERCEPTOR(int, putenv, char *string) { 616 ENSURE_MSAN_INITED(); 617 int res = REAL(putenv)(string); 618 if (!res) UnpoisonEnviron(); 619 return res; 620 } 621 622 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { 623 ENSURE_MSAN_INITED(); 624 int res = REAL(__fxstat)(magic, fd, buf); 625 if (!res) 626 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 627 return res; 628 } 629 630 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { 631 ENSURE_MSAN_INITED(); 632 int res = REAL(__fxstat64)(magic, fd, buf); 633 if (!res) 634 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 635 return res; 636 } 637 638 INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf, 639 int flags) { 640 ENSURE_MSAN_INITED(); 641 int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags); 642 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz); 643 return res; 644 } 645 646 INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf, 647 int flags) { 648 ENSURE_MSAN_INITED(); 649 int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags); 650 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 651 return res; 652 } 653 654 INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) { 655 ENSURE_MSAN_INITED(); 656 int res = REAL(__xstat)(magic, path, buf); 657 if (!res) 658 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 659 return res; 660 } 661 662 INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) { 663 ENSURE_MSAN_INITED(); 664 int res = REAL(__xstat64)(magic, path, buf); 665 if (!res) 666 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 667 return res; 668 } 669 670 INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) { 671 ENSURE_MSAN_INITED(); 672 int res = REAL(__lxstat)(magic, path, buf); 673 if (!res) 674 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 675 return res; 676 } 677 678 INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) { 679 ENSURE_MSAN_INITED(); 680 int res = REAL(__lxstat64)(magic, path, buf); 681 if (!res) 682 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 683 return res; 684 } 685 686 INTERCEPTOR(int, pipe, int pipefd[2]) { 687 if (msan_init_is_running) 688 return REAL(pipe)(pipefd); 689 ENSURE_MSAN_INITED(); 690 int res = REAL(pipe)(pipefd); 691 if (!res) 692 __msan_unpoison(pipefd, sizeof(int[2])); 693 return res; 694 } 695 696 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) { 697 ENSURE_MSAN_INITED(); 698 int res = REAL(pipe2)(pipefd, flags); 699 if (!res) 700 __msan_unpoison(pipefd, sizeof(int[2])); 701 return res; 702 } 703 704 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) { 705 ENSURE_MSAN_INITED(); 706 int res = REAL(socketpair)(domain, type, protocol, sv); 707 if (!res) 708 __msan_unpoison(sv, sizeof(int[2])); 709 return res; 710 } 711 712 INTERCEPTOR(char *, fgets, char *s, int size, void *stream) { 713 ENSURE_MSAN_INITED(); 714 char *res = REAL(fgets)(s, size, stream); 715 if (res) 716 __msan_unpoison(s, REAL(strlen)(s) + 1); 717 return res; 718 } 719 720 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { 721 ENSURE_MSAN_INITED(); 722 char *res = REAL(fgets_unlocked)(s, size, stream); 723 if (res) 724 __msan_unpoison(s, REAL(strlen)(s) + 1); 725 return res; 726 } 727 728 INTERCEPTOR(int, getrlimit, int resource, void *rlim) { 729 if (msan_init_is_running) 730 return REAL(getrlimit)(resource, rlim); 731 ENSURE_MSAN_INITED(); 732 int res = REAL(getrlimit)(resource, rlim); 733 if (!res) 734 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); 735 return res; 736 } 737 738 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) { 739 if (msan_init_is_running) 740 return REAL(getrlimit64)(resource, rlim); 741 ENSURE_MSAN_INITED(); 742 int res = REAL(getrlimit64)(resource, rlim); 743 if (!res) 744 __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz); 745 return res; 746 } 747 748 INTERCEPTOR(int, uname, void *utsname) { 749 ENSURE_MSAN_INITED(); 750 int res = REAL(uname)(utsname); 751 if (!res) { 752 __msan_unpoison(utsname, __sanitizer::struct_utsname_sz); 753 } 754 return res; 755 } 756 757 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) { 758 ENSURE_MSAN_INITED(); 759 int res = REAL(gethostname)(name, len); 760 if (!res) { 761 SIZE_T real_len = REAL(strnlen)(name, len); 762 if (real_len < len) 763 ++real_len; 764 __msan_unpoison(name, real_len); 765 } 766 return res; 767 } 768 769 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents, 770 int timeout) { 771 ENSURE_MSAN_INITED(); 772 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout); 773 if (res > 0) { 774 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 775 } 776 return res; 777 } 778 779 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, 780 int timeout, void *sigmask) { 781 ENSURE_MSAN_INITED(); 782 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask); 783 if (res > 0) { 784 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 785 } 786 return res; 787 } 788 789 INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { 790 ENSURE_MSAN_INITED(); 791 SSIZE_T res = REAL(recv)(fd, buf, len, flags); 792 if (res > 0) 793 __msan_unpoison(buf, res); 794 return res; 795 } 796 797 INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, 798 void *srcaddr, int *addrlen) { 799 ENSURE_MSAN_INITED(); 800 SIZE_T srcaddr_sz; 801 if (srcaddr) srcaddr_sz = *addrlen; 802 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); 803 if (res > 0) { 804 __msan_unpoison(buf, res); 805 if (srcaddr) { 806 SIZE_T sz = *addrlen; 807 __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz); 808 } 809 } 810 return res; 811 } 812 813 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { 814 if (CallocShouldReturnNullDueToOverflow(size, nmemb)) 815 return AllocatorReturnNull(); 816 GET_MALLOC_STACK_TRACE; 817 if (!msan_inited) { 818 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 819 const SIZE_T kCallocPoolSize = 1024; 820 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 821 static SIZE_T allocated; 822 SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 823 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 824 allocated += size_in_words; 825 CHECK(allocated < kCallocPoolSize); 826 return mem; 827 } 828 return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true); 829 } 830 831 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { 832 GET_MALLOC_STACK_TRACE; 833 return MsanReallocate(&stack, ptr, size, sizeof(u64), false); 834 } 835 836 INTERCEPTOR(void *, malloc, SIZE_T size) { 837 GET_MALLOC_STACK_TRACE; 838 return MsanReallocate(&stack, 0, size, sizeof(u64), false); 839 } 840 841 void __msan_allocated_memory(const void* data, uptr size) { 842 GET_MALLOC_STACK_TRACE; 843 if (flags()->poison_in_malloc) 844 __msan_poison(data, size); 845 if (__msan_get_track_origins()) { 846 u32 stack_id = StackDepotPut(stack.trace, stack.size); 847 u32 id; 848 ChainedOriginDepotPut(stack_id, Origin::kHeapRoot, &id); 849 __msan_set_origin(data, size, Origin(id, 1).raw_id()); 850 } 851 } 852 853 INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, 854 int fd, OFF_T offset) { 855 ENSURE_MSAN_INITED(); 856 if (addr && !MEM_IS_APP(addr)) { 857 if (flags & map_fixed) { 858 *__errno_location() = errno_EINVAL; 859 return (void *)-1; 860 } else { 861 addr = 0; 862 } 863 } 864 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset); 865 if (res != (void*)-1) 866 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 867 return res; 868 } 869 870 INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, 871 int fd, OFF64_T offset) { 872 ENSURE_MSAN_INITED(); 873 if (addr && !MEM_IS_APP(addr)) { 874 if (flags & map_fixed) { 875 *__errno_location() = errno_EINVAL; 876 return (void *)-1; 877 } else { 878 addr = 0; 879 } 880 } 881 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset); 882 if (res != (void*)-1) 883 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 884 return res; 885 } 886 887 struct dlinfo { 888 char *dli_fname; 889 void *dli_fbase; 890 char *dli_sname; 891 void *dli_saddr; 892 }; 893 894 INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { 895 ENSURE_MSAN_INITED(); 896 int res = REAL(dladdr)(addr, info); 897 if (res != 0) { 898 __msan_unpoison(info, sizeof(*info)); 899 if (info->dli_fname) 900 __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); 901 if (info->dli_sname) 902 __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); 903 } 904 return res; 905 } 906 907 INTERCEPTOR(char *, dlerror, int fake) { 908 ENSURE_MSAN_INITED(); 909 char *res = REAL(dlerror)(fake); 910 if (res != 0) __msan_unpoison(res, REAL(strlen)(res) + 1); 911 return res; 912 } 913 914 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, 915 void *data); 916 struct dl_iterate_phdr_data { 917 dl_iterate_phdr_cb callback; 918 void *data; 919 }; 920 921 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, 922 void *data) { 923 if (info) { 924 __msan_unpoison(info, size); 925 if (info->dlpi_name) 926 __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); 927 } 928 dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; 929 UnpoisonParam(3); 930 return IndirectExternCall(cbdata->callback)(info, size, cbdata->data); 931 } 932 933 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { 934 ENSURE_MSAN_INITED(); 935 EnterLoader(); 936 dl_iterate_phdr_data cbdata; 937 cbdata.callback = callback; 938 cbdata.data = data; 939 int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); 940 ExitLoader(); 941 return res; 942 } 943 944 INTERCEPTOR(int, getrusage, int who, void *usage) { 945 ENSURE_MSAN_INITED(); 946 int res = REAL(getrusage)(who, usage); 947 if (res == 0) { 948 __msan_unpoison(usage, __sanitizer::struct_rusage_sz); 949 } 950 return res; 951 } 952 953 class SignalHandlerScope { 954 public: 955 SignalHandlerScope() { 956 if (MsanThread *t = GetCurrentThread()) 957 t->EnterSignalHandler(); 958 } 959 ~SignalHandlerScope() { 960 if (MsanThread *t = GetCurrentThread()) 961 t->LeaveSignalHandler(); 962 } 963 }; 964 965 // sigactions_mu guarantees atomicity of sigaction() and signal() calls. 966 // Access to sigactions[] is gone with relaxed atomics to avoid data race with 967 // the signal handler. 968 const int kMaxSignals = 1024; 969 static atomic_uintptr_t sigactions[kMaxSignals]; 970 static StaticSpinMutex sigactions_mu; 971 972 static void SignalHandler(int signo) { 973 SignalHandlerScope signal_handler_scope; 974 ScopedThreadLocalStateBackup stlsb; 975 UnpoisonParam(1); 976 977 typedef void (*signal_cb)(int x); 978 signal_cb cb = 979 (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 980 IndirectExternCall(cb)(signo); 981 } 982 983 static void SignalAction(int signo, void *si, void *uc) { 984 SignalHandlerScope signal_handler_scope; 985 ScopedThreadLocalStateBackup stlsb; 986 UnpoisonParam(3); 987 __msan_unpoison(si, sizeof(__sanitizer_sigaction)); 988 __msan_unpoison(uc, __sanitizer::ucontext_t_sz); 989 990 typedef void (*sigaction_cb)(int, void *, void *); 991 sigaction_cb cb = 992 (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 993 IndirectExternCall(cb)(signo, si, uc); 994 } 995 996 INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, 997 __sanitizer_sigaction *oldact) { 998 ENSURE_MSAN_INITED(); 999 // FIXME: check that *act is unpoisoned. 1000 // That requires intercepting all of sigemptyset, sigfillset, etc. 1001 int res; 1002 if (flags()->wrap_signals) { 1003 SpinMutexLock lock(&sigactions_mu); 1004 CHECK_LT(signo, kMaxSignals); 1005 uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); 1006 __sanitizer_sigaction new_act; 1007 __sanitizer_sigaction *pnew_act = act ? &new_act : 0; 1008 if (act) { 1009 internal_memcpy(pnew_act, act, sizeof(__sanitizer_sigaction)); 1010 uptr cb = (uptr)pnew_act->sigaction; 1011 uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo) 1012 ? (uptr)SignalAction 1013 : (uptr)SignalHandler; 1014 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1015 atomic_store(&sigactions[signo], cb, memory_order_relaxed); 1016 pnew_act->sigaction = (void (*)(int, void *, void *))new_cb; 1017 } 1018 } 1019 res = REAL(sigaction)(signo, pnew_act, oldact); 1020 if (res == 0 && oldact) { 1021 uptr cb = (uptr)oldact->sigaction; 1022 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1023 oldact->sigaction = (void (*)(int, void *, void *))old_cb; 1024 } 1025 } 1026 } else { 1027 res = REAL(sigaction)(signo, act, oldact); 1028 } 1029 1030 if (res == 0 && oldact) { 1031 __msan_unpoison(oldact, sizeof(__sanitizer_sigaction)); 1032 } 1033 return res; 1034 } 1035 1036 INTERCEPTOR(int, signal, int signo, uptr cb) { 1037 ENSURE_MSAN_INITED(); 1038 if (flags()->wrap_signals) { 1039 CHECK_LT(signo, kMaxSignals); 1040 SpinMutexLock lock(&sigactions_mu); 1041 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1042 atomic_store(&sigactions[signo], cb, memory_order_relaxed); 1043 cb = (uptr) SignalHandler; 1044 } 1045 return REAL(signal)(signo, cb); 1046 } else { 1047 return REAL(signal)(signo, cb); 1048 } 1049 } 1050 1051 extern "C" int pthread_attr_init(void *attr); 1052 extern "C" int pthread_attr_destroy(void *attr); 1053 1054 static void *MsanThreadStartFunc(void *arg) { 1055 MsanThread *t = (MsanThread *)arg; 1056 SetCurrentThread(t); 1057 return t->ThreadStart(); 1058 } 1059 1060 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), 1061 void * param) { 1062 ENSURE_MSAN_INITED(); // for GetTlsSize() 1063 __sanitizer_pthread_attr_t myattr; 1064 if (attr == 0) { 1065 pthread_attr_init(&myattr); 1066 attr = &myattr; 1067 } 1068 1069 AdjustStackSize(attr); 1070 1071 MsanThread *t = MsanThread::Create(callback, param); 1072 1073 int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t); 1074 1075 if (attr == &myattr) 1076 pthread_attr_destroy(&myattr); 1077 if (!res) { 1078 __msan_unpoison(th, __sanitizer::pthread_t_sz); 1079 } 1080 return res; 1081 } 1082 1083 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key, 1084 void (*dtor)(void *value)) { 1085 if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor); 1086 ENSURE_MSAN_INITED(); 1087 int res = REAL(pthread_key_create)(key, dtor); 1088 if (!res && key) 1089 __msan_unpoison(key, sizeof(*key)); 1090 return res; 1091 } 1092 1093 INTERCEPTOR(int, pthread_join, void *th, void **retval) { 1094 ENSURE_MSAN_INITED(); 1095 int res = REAL(pthread_join)(th, retval); 1096 if (!res && retval) 1097 __msan_unpoison(retval, sizeof(*retval)); 1098 return res; 1099 } 1100 1101 extern char *tzname[2]; 1102 1103 INTERCEPTOR(void, tzset, int fake) { 1104 ENSURE_MSAN_INITED(); 1105 REAL(tzset)(fake); 1106 if (tzname[0]) 1107 __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1); 1108 if (tzname[1]) 1109 __msan_unpoison(tzname[1], REAL(strlen)(tzname[1]) + 1); 1110 return; 1111 } 1112 1113 struct MSanAtExitRecord { 1114 void (*func)(void *arg); 1115 void *arg; 1116 }; 1117 1118 void MSanAtExitWrapper(void *arg) { 1119 UnpoisonParam(1); 1120 MSanAtExitRecord *r = (MSanAtExitRecord *)arg; 1121 IndirectExternCall(r->func)(r->arg); 1122 InternalFree(r); 1123 } 1124 1125 // Unpoison argument shadow for C++ module destructors. 1126 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 1127 void *dso_handle) { 1128 if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle); 1129 ENSURE_MSAN_INITED(); 1130 MSanAtExitRecord *r = 1131 (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord)); 1132 r->func = func; 1133 r->arg = arg; 1134 return REAL(__cxa_atexit)(MSanAtExitWrapper, r, dso_handle); 1135 } 1136 1137 DECLARE_REAL(int, shmctl, int shmid, int cmd, void *buf) 1138 1139 INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) { 1140 ENSURE_MSAN_INITED(); 1141 void *p = REAL(shmat)(shmid, shmaddr, shmflg); 1142 if (p != (void *)-1) { 1143 __sanitizer_shmid_ds ds; 1144 int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds); 1145 if (!res) { 1146 __msan_unpoison(p, ds.shm_segsz); 1147 } 1148 } 1149 return p; 1150 } 1151 1152 // Linux kernel has a bug that leads to kernel deadlock if a process 1153 // maps TBs of memory and then calls mlock(). 1154 static void MlockIsUnsupported() { 1155 static atomic_uint8_t printed; 1156 if (atomic_exchange(&printed, 1, memory_order_relaxed)) 1157 return; 1158 VPrintf(1, 1159 "INFO: MemorySanitizer ignores mlock/mlockall/munlock/munlockall\n"); 1160 } 1161 1162 INTERCEPTOR(int, mlock, const void *addr, uptr len) { 1163 MlockIsUnsupported(); 1164 return 0; 1165 } 1166 1167 INTERCEPTOR(int, munlock, const void *addr, uptr len) { 1168 MlockIsUnsupported(); 1169 return 0; 1170 } 1171 1172 INTERCEPTOR(int, mlockall, int flags) { 1173 MlockIsUnsupported(); 1174 return 0; 1175 } 1176 1177 INTERCEPTOR(int, munlockall, void) { 1178 MlockIsUnsupported(); 1179 return 0; 1180 } 1181 1182 struct MSanInterceptorContext { 1183 bool in_interceptor_scope; 1184 }; 1185 1186 namespace __msan { 1187 1188 int OnExit() { 1189 // FIXME: ask frontend whether we need to return failure. 1190 return 0; 1191 } 1192 1193 } // namespace __msan 1194 1195 // A version of CHECK_UNPOISONED using a saved scope value. Used in common 1196 // interceptors. 1197 #define CHECK_UNPOISONED_CTX(ctx, x, n) \ 1198 do { \ 1199 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \ 1200 CHECK_UNPOISONED_0(x, n); \ 1201 } while (0) 1202 1203 #define MSAN_INTERCEPT_FUNC(name) \ 1204 do { \ 1205 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ 1206 VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \ 1207 } while (0) 1208 1209 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name) 1210 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \ 1211 UnpoisonParam(count) 1212 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 1213 __msan_unpoison(ptr, size) 1214 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 1215 CHECK_UNPOISONED_CTX(ctx, ptr, size) 1216 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \ 1217 __msan_unpoison(ptr, size) 1218 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 1219 if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \ 1220 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \ 1221 ctx = (void *)&msan_ctx; \ 1222 (void)ctx; \ 1223 InterceptorScope interceptor_scope; \ 1224 __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ \ 1225 ENSURE_MSAN_INITED(); 1226 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 1227 do { \ 1228 } while (false) 1229 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 1230 do { \ 1231 } while (false) 1232 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 1233 do { \ 1234 } while (false) 1235 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ 1236 do { \ 1237 } while (false) // FIXME 1238 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 1239 do { \ 1240 } while (false) // FIXME 1241 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 1242 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 1243 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) \ 1244 if (!__msan_has_dynamic_component() && map) { \ 1245 /* If msandr didn't clear the shadow before the initializers ran, we do */ \ 1246 /* it ourselves afterwards. */ \ 1247 ForEachMappedRegion((link_map *)map, __msan_unpoison); \ 1248 } 1249 1250 #include "sanitizer_common/sanitizer_common_interceptors.inc" 1251 1252 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) 1253 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ 1254 do { \ 1255 } while (false) 1256 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 1257 do { \ 1258 } while (false) 1259 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s) 1260 #include "sanitizer_common/sanitizer_common_syscalls.inc" 1261 1262 // static 1263 void *fast_memset(void *ptr, int c, SIZE_T n) { 1264 // hack until we have a really fast internal_memset 1265 if (sizeof(uptr) == 8 && 1266 (n % 8) == 0 && 1267 ((uptr)ptr % 8) == 0) { 1268 uptr c8 = (unsigned)c & 0xFF; 1269 c8 = (c8 << 8) | c8; 1270 c8 = (c8 << 16) | c8; 1271 c8 = (c8 << 32) | c8; 1272 uptr *p = (uptr*)ptr; 1273 for (SIZE_T i = 0; i < n / 8; i++) 1274 p[i] = c8; 1275 return ptr; 1276 } 1277 return internal_memset(ptr, c, n); 1278 } 1279 1280 // static 1281 void *fast_memcpy(void *dst, const void *src, SIZE_T n) { 1282 // Same hack as in fast_memset above. 1283 if (sizeof(uptr) == 8 && 1284 (n % 8) == 0 && 1285 ((uptr)dst % 8) == 0 && 1286 ((uptr)src % 8) == 0) { 1287 uptr *d = (uptr*)dst; 1288 uptr *s = (uptr*)src; 1289 for (SIZE_T i = 0; i < n / 8; i++) 1290 d[i] = s[i]; 1291 return dst; 1292 } 1293 return internal_memcpy(dst, src, n); 1294 } 1295 1296 static void PoisonShadow(uptr ptr, uptr size, u8 value) { 1297 uptr PageSize = GetPageSizeCached(); 1298 uptr shadow_beg = MEM_TO_SHADOW(ptr); 1299 uptr shadow_end = MEM_TO_SHADOW(ptr + size); 1300 if (value || 1301 shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) { 1302 fast_memset((void*)shadow_beg, value, shadow_end - shadow_beg); 1303 } else { 1304 uptr page_beg = RoundUpTo(shadow_beg, PageSize); 1305 uptr page_end = RoundDownTo(shadow_end, PageSize); 1306 1307 if (page_beg >= page_end) { 1308 fast_memset((void *)shadow_beg, 0, shadow_end - shadow_beg); 1309 } else { 1310 if (page_beg != shadow_beg) { 1311 fast_memset((void *)shadow_beg, 0, page_beg - shadow_beg); 1312 } 1313 if (page_end != shadow_end) { 1314 fast_memset((void *)page_end, 0, shadow_end - page_end); 1315 } 1316 MmapFixedNoReserve(page_beg, page_end - page_beg); 1317 } 1318 } 1319 } 1320 1321 // These interface functions reside here so that they can use 1322 // fast_memset, etc. 1323 void __msan_unpoison(const void *a, uptr size) { 1324 if (!MEM_IS_APP(a)) return; 1325 PoisonShadow((uptr)a, size, 0); 1326 } 1327 1328 void __msan_poison(const void *a, uptr size) { 1329 if (!MEM_IS_APP(a)) return; 1330 PoisonShadow((uptr)a, size, 1331 __msan::flags()->poison_heap_with_zeroes ? 0 : -1); 1332 } 1333 1334 void __msan_poison_stack(void *a, uptr size) { 1335 if (!MEM_IS_APP(a)) return; 1336 PoisonShadow((uptr)a, size, 1337 __msan::flags()->poison_stack_with_zeroes ? 0 : -1); 1338 } 1339 1340 void __msan_clear_and_unpoison(void *a, uptr size) { 1341 fast_memset(a, 0, size); 1342 PoisonShadow((uptr)a, size, 0); 1343 } 1344 1345 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) { 1346 if (!msan_inited) return internal_memcpy(dest, src, n); 1347 if (msan_init_is_running) return REAL(memcpy)(dest, src, n); 1348 ENSURE_MSAN_INITED(); 1349 GET_STORE_STACK_TRACE; 1350 void *res = fast_memcpy(dest, src, n); 1351 CopyPoison(dest, src, n, &stack); 1352 return res; 1353 } 1354 1355 void *__msan_memset(void *s, int c, SIZE_T n) { 1356 if (!msan_inited) return internal_memset(s, c, n); 1357 if (msan_init_is_running) return REAL(memset)(s, c, n); 1358 ENSURE_MSAN_INITED(); 1359 void *res = fast_memset(s, c, n); 1360 __msan_unpoison(s, n); 1361 return res; 1362 } 1363 1364 void *__msan_memmove(void *dest, const void *src, SIZE_T n) { 1365 if (!msan_inited) return internal_memmove(dest, src, n); 1366 if (msan_init_is_running) return REAL(memmove)(dest, src, n); 1367 ENSURE_MSAN_INITED(); 1368 GET_STORE_STACK_TRACE; 1369 void *res = REAL(memmove)(dest, src, n); 1370 MovePoison(dest, src, n, &stack); 1371 return res; 1372 } 1373 1374 void __msan_unpoison_string(const char* s) { 1375 if (!MEM_IS_APP(s)) return; 1376 __msan_unpoison(s, REAL(strlen)(s) + 1); 1377 } 1378 1379 namespace __msan { 1380 1381 u32 GetOriginIfPoisoned(uptr addr, uptr size) { 1382 unsigned char *s = (unsigned char *)MEM_TO_SHADOW(addr); 1383 for (uptr i = 0; i < size; ++i) 1384 if (s[i]) 1385 return *(u32 *)SHADOW_TO_ORIGIN((s + i) & ~3UL); 1386 return 0; 1387 } 1388 1389 void SetOriginIfPoisoned(uptr addr, uptr src_shadow, uptr size, 1390 u32 src_origin) { 1391 uptr dst_s = MEM_TO_SHADOW(addr); 1392 uptr src_s = src_shadow; 1393 uptr src_s_end = src_s + size; 1394 1395 for (; src_s < src_s_end; ++dst_s, ++src_s) 1396 if (*(u8 *)src_s) *(u32 *)SHADOW_TO_ORIGIN(dst_s &~3UL) = src_origin; 1397 } 1398 1399 void CopyOrigin(void *dst, const void *src, uptr size, StackTrace *stack) { 1400 if (!__msan_get_track_origins()) return; 1401 if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return; 1402 1403 uptr d = (uptr)dst; 1404 uptr beg = d & ~3UL; 1405 // Copy left unaligned origin if that memory is poisoned. 1406 if (beg < d) { 1407 u32 o = GetOriginIfPoisoned((uptr)src, d - beg); 1408 if (o) { 1409 if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack); 1410 *(u32 *)MEM_TO_ORIGIN(beg) = o; 1411 } 1412 beg += 4; 1413 } 1414 1415 uptr end = (d + size) & ~3UL; 1416 // If both ends fall into the same 4-byte slot, we are done. 1417 if (end < beg) return; 1418 1419 // Copy right unaligned origin if that memory is poisoned. 1420 if (end < d + size) { 1421 u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end); 1422 if (o) { 1423 if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack); 1424 *(u32 *)MEM_TO_ORIGIN(end) = o; 1425 } 1426 } 1427 1428 if (beg < end) { 1429 // Align src up. 1430 uptr s = ((uptr)src + 3) & ~3UL; 1431 // FIXME: factor out to msan_copy_origin_aligned 1432 if (__msan_get_track_origins() > 1) { 1433 u32 *src = (u32 *)MEM_TO_ORIGIN(s); 1434 u32 *src_s = (u32 *)MEM_TO_SHADOW(s); 1435 u32 *src_end = (u32 *)MEM_TO_ORIGIN(s + (end - beg)); 1436 u32 *dst = (u32 *)MEM_TO_ORIGIN(beg); 1437 u32 src_o = 0; 1438 u32 dst_o = 0; 1439 for (; src < src_end; ++src, ++src_s, ++dst) { 1440 if (!*src_s) continue; 1441 if (*src != src_o) { 1442 src_o = *src; 1443 dst_o = ChainOrigin(src_o, stack); 1444 } 1445 *dst = dst_o; 1446 } 1447 } else { 1448 fast_memcpy((void *)MEM_TO_ORIGIN(beg), (void *)MEM_TO_ORIGIN(s), 1449 end - beg); 1450 } 1451 } 1452 } 1453 1454 void MovePoison(void *dst, const void *src, uptr size, StackTrace *stack) { 1455 if (!MEM_IS_APP(dst)) return; 1456 if (!MEM_IS_APP(src)) return; 1457 if (src == dst) return; 1458 internal_memmove((void *)MEM_TO_SHADOW((uptr)dst), 1459 (void *)MEM_TO_SHADOW((uptr)src), size); 1460 CopyOrigin(dst, src, size, stack); 1461 } 1462 1463 void CopyPoison(void *dst, const void *src, uptr size, StackTrace *stack) { 1464 if (!MEM_IS_APP(dst)) return; 1465 if (!MEM_IS_APP(src)) return; 1466 fast_memcpy((void *)MEM_TO_SHADOW((uptr)dst), 1467 (void *)MEM_TO_SHADOW((uptr)src), size); 1468 CopyOrigin(dst, src, size, stack); 1469 } 1470 1471 void InitializeInterceptors() { 1472 static int inited = 0; 1473 CHECK_EQ(inited, 0); 1474 InitializeCommonInterceptors(); 1475 1476 INTERCEPT_FUNCTION(mmap); 1477 INTERCEPT_FUNCTION(mmap64); 1478 INTERCEPT_FUNCTION(posix_memalign); 1479 INTERCEPT_FUNCTION(memalign); 1480 INTERCEPT_FUNCTION(__libc_memalign); 1481 INTERCEPT_FUNCTION(valloc); 1482 INTERCEPT_FUNCTION(pvalloc); 1483 INTERCEPT_FUNCTION(malloc); 1484 INTERCEPT_FUNCTION(calloc); 1485 INTERCEPT_FUNCTION(realloc); 1486 INTERCEPT_FUNCTION(free); 1487 INTERCEPT_FUNCTION(cfree); 1488 INTERCEPT_FUNCTION(malloc_usable_size); 1489 INTERCEPT_FUNCTION(mallinfo); 1490 INTERCEPT_FUNCTION(mallopt); 1491 INTERCEPT_FUNCTION(malloc_stats); 1492 INTERCEPT_FUNCTION(fread); 1493 INTERCEPT_FUNCTION(fread_unlocked); 1494 INTERCEPT_FUNCTION(readlink); 1495 INTERCEPT_FUNCTION(memcpy); 1496 INTERCEPT_FUNCTION(memccpy); 1497 INTERCEPT_FUNCTION(mempcpy); 1498 INTERCEPT_FUNCTION(memset); 1499 INTERCEPT_FUNCTION(memmove); 1500 INTERCEPT_FUNCTION(bcopy); 1501 INTERCEPT_FUNCTION(wmemset); 1502 INTERCEPT_FUNCTION(wmemcpy); 1503 INTERCEPT_FUNCTION(wmempcpy); 1504 INTERCEPT_FUNCTION(wmemmove); 1505 INTERCEPT_FUNCTION(strcpy); // NOLINT 1506 INTERCEPT_FUNCTION(stpcpy); // NOLINT 1507 INTERCEPT_FUNCTION(strdup); 1508 INTERCEPT_FUNCTION(__strdup); 1509 INTERCEPT_FUNCTION(strndup); 1510 INTERCEPT_FUNCTION(__strndup); 1511 INTERCEPT_FUNCTION(strncpy); // NOLINT 1512 INTERCEPT_FUNCTION(strlen); 1513 INTERCEPT_FUNCTION(strnlen); 1514 INTERCEPT_FUNCTION(gcvt); 1515 INTERCEPT_FUNCTION(strcat); // NOLINT 1516 INTERCEPT_FUNCTION(strncat); // NOLINT 1517 INTERCEPT_FUNCTION(strtod); 1518 INTERCEPT_FUNCTION(strtof); 1519 INTERCEPT_FUNCTION(strtold); 1520 INTERCEPT_FUNCTION(strtol); 1521 INTERCEPT_FUNCTION(strtoll); 1522 INTERCEPT_FUNCTION(strtoul); 1523 INTERCEPT_FUNCTION(strtoull); 1524 INTERCEPT_FUNCTION(strtod_l); 1525 INTERCEPT_FUNCTION(__strtod_l); 1526 INTERCEPT_FUNCTION(__strtod_internal); 1527 INTERCEPT_FUNCTION(strtof_l); 1528 INTERCEPT_FUNCTION(__strtof_l); 1529 INTERCEPT_FUNCTION(__strtof_internal); 1530 INTERCEPT_FUNCTION(strtold_l); 1531 INTERCEPT_FUNCTION(__strtold_l); 1532 INTERCEPT_FUNCTION(__strtold_internal); 1533 INTERCEPT_FUNCTION(strtol_l); 1534 INTERCEPT_FUNCTION(__strtol_l); 1535 INTERCEPT_FUNCTION(__strtol_internal); 1536 INTERCEPT_FUNCTION(strtoll_l); 1537 INTERCEPT_FUNCTION(__strtoll_l); 1538 INTERCEPT_FUNCTION(__strtoll_internal); 1539 INTERCEPT_FUNCTION(strtoul_l); 1540 INTERCEPT_FUNCTION(__strtoul_l); 1541 INTERCEPT_FUNCTION(__strtoul_internal); 1542 INTERCEPT_FUNCTION(strtoull_l); 1543 INTERCEPT_FUNCTION(__strtoull_l); 1544 INTERCEPT_FUNCTION(__strtoull_internal); 1545 INTERCEPT_FUNCTION(vswprintf); 1546 INTERCEPT_FUNCTION(swprintf); 1547 INTERCEPT_FUNCTION(strxfrm); 1548 INTERCEPT_FUNCTION(strxfrm_l); 1549 INTERCEPT_FUNCTION(strftime); 1550 INTERCEPT_FUNCTION(strftime_l); 1551 INTERCEPT_FUNCTION(__strftime_l); 1552 INTERCEPT_FUNCTION(wcsftime); 1553 INTERCEPT_FUNCTION(wcsftime_l); 1554 INTERCEPT_FUNCTION(__wcsftime_l); 1555 INTERCEPT_FUNCTION(mbtowc); 1556 INTERCEPT_FUNCTION(mbrtowc); 1557 INTERCEPT_FUNCTION(wcslen); 1558 INTERCEPT_FUNCTION(wcschr); 1559 INTERCEPT_FUNCTION(wcscpy); 1560 INTERCEPT_FUNCTION(wcscmp); 1561 INTERCEPT_FUNCTION(wcstod); 1562 INTERCEPT_FUNCTION(getenv); 1563 INTERCEPT_FUNCTION(setenv); 1564 INTERCEPT_FUNCTION(putenv); 1565 INTERCEPT_FUNCTION(gettimeofday); 1566 INTERCEPT_FUNCTION(fcvt); 1567 INTERCEPT_FUNCTION(__fxstat); 1568 INTERCEPT_FUNCTION(__fxstatat); 1569 INTERCEPT_FUNCTION(__xstat); 1570 INTERCEPT_FUNCTION(__lxstat); 1571 INTERCEPT_FUNCTION(__fxstat64); 1572 INTERCEPT_FUNCTION(__fxstatat64); 1573 INTERCEPT_FUNCTION(__xstat64); 1574 INTERCEPT_FUNCTION(__lxstat64); 1575 INTERCEPT_FUNCTION(pipe); 1576 INTERCEPT_FUNCTION(pipe2); 1577 INTERCEPT_FUNCTION(socketpair); 1578 INTERCEPT_FUNCTION(fgets); 1579 INTERCEPT_FUNCTION(fgets_unlocked); 1580 INTERCEPT_FUNCTION(getrlimit); 1581 INTERCEPT_FUNCTION(getrlimit64); 1582 INTERCEPT_FUNCTION(uname); 1583 INTERCEPT_FUNCTION(gethostname); 1584 INTERCEPT_FUNCTION(epoll_wait); 1585 INTERCEPT_FUNCTION(epoll_pwait); 1586 INTERCEPT_FUNCTION(recv); 1587 INTERCEPT_FUNCTION(recvfrom); 1588 INTERCEPT_FUNCTION(dladdr); 1589 INTERCEPT_FUNCTION(dlerror); 1590 INTERCEPT_FUNCTION(dl_iterate_phdr); 1591 INTERCEPT_FUNCTION(getrusage); 1592 INTERCEPT_FUNCTION(sigaction); 1593 INTERCEPT_FUNCTION(signal); 1594 INTERCEPT_FUNCTION(pthread_create); 1595 INTERCEPT_FUNCTION(pthread_key_create); 1596 INTERCEPT_FUNCTION(pthread_join); 1597 INTERCEPT_FUNCTION(tzset); 1598 INTERCEPT_FUNCTION(__cxa_atexit); 1599 INTERCEPT_FUNCTION(shmat); 1600 1601 inited = 1; 1602 } 1603 } // namespace __msan 1604