msan_interceptors.cc revision 97160a83ae2dad479cd93a3cb1dfbc06958f69a1
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 "interception/interception.h" 19#include "msan.h" 20#include "sanitizer_common/sanitizer_platform_limits_posix.h" 21#include "sanitizer_common/sanitizer_allocator.h" 22#include "sanitizer_common/sanitizer_atomic.h" 23#include "sanitizer_common/sanitizer_common.h" 24#include "sanitizer_common/sanitizer_stackdepot.h" 25#include "sanitizer_common/sanitizer_libc.h" 26#include "sanitizer_common/sanitizer_linux.h" 27 28#include <stdarg.h> 29// ACHTUNG! No other system header includes in this file. 30// Ideally, we should get rid of stdarg.h as well. 31 32using namespace __msan; 33 34using __sanitizer::memory_order; 35using __sanitizer::atomic_load; 36using __sanitizer::atomic_store; 37using __sanitizer::atomic_uintptr_t; 38 39// True if this is a nested interceptor. 40static THREADLOCAL int in_interceptor_scope; 41 42struct InterceptorScope { 43 InterceptorScope() { ++in_interceptor_scope; } 44 ~InterceptorScope() { --in_interceptor_scope; } 45}; 46 47bool IsInInterceptorScope() { 48 return in_interceptor_scope; 49} 50 51#define ENSURE_MSAN_INITED() do { \ 52 CHECK(!msan_init_is_running); \ 53 if (!msan_inited) { \ 54 __msan_init(); \ 55 } \ 56} while (0) 57 58// Check that [x, x+n) range is unpoisoned. 59#define CHECK_UNPOISONED_0(x, n) \ 60 do { \ 61 sptr offset = __msan_test_shadow(x, n); \ 62 if (__msan::IsInSymbolizer()) break; \ 63 if (offset >= 0 && __msan::flags()->report_umrs) { \ 64 GET_CALLER_PC_BP_SP; \ 65 (void) sp; \ 66 Printf("UMR in %s at offset %d inside [%p, +%d) \n", __FUNCTION__, \ 67 offset, x, n); \ 68 __msan::PrintWarningWithOrigin(pc, bp, \ 69 __msan_get_origin((char *)x + offset)); \ 70 if (__msan::flags()->halt_on_error) { \ 71 Printf("Exiting\n"); \ 72 Die(); \ 73 } \ 74 } \ 75 } while (0) 76 77// Check that [x, x+n) range is unpoisoned unless we are in a nested 78// interceptor. 79#define CHECK_UNPOISONED(x, n) \ 80 do { \ 81 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \ 82 } while (0); 83 84static void *fast_memset(void *ptr, int c, SIZE_T n); 85static void *fast_memcpy(void *dst, const void *src, SIZE_T n); 86 87INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) { 88 ENSURE_MSAN_INITED(); 89 SIZE_T res = REAL(fread)(ptr, size, nmemb, file); 90 if (res > 0) 91 __msan_unpoison(ptr, res *size); 92 return res; 93} 94 95INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb, 96 void *file) { 97 ENSURE_MSAN_INITED(); 98 SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file); 99 if (res > 0) 100 __msan_unpoison(ptr, res *size); 101 return res; 102} 103 104INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) { 105 ENSURE_MSAN_INITED(); 106 SSIZE_T res = REAL(readlink)(path, buf, bufsiz); 107 if (res > 0) 108 __msan_unpoison(buf, res); 109 return res; 110} 111 112INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) { 113 return __msan_memcpy(dest, src, n); 114} 115 116INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) { 117 return (char *)__msan_memcpy(dest, src, n) + n; 118} 119 120INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) { 121 return __msan_memmove(dest, src, n); 122} 123 124INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) { 125 return __msan_memset(s, c, n); 126} 127 128INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) { 129 return __msan_memmove(dest, src, n); 130} 131 132INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) { 133 GET_MALLOC_STACK_TRACE; 134 CHECK_EQ(alignment & (alignment - 1), 0); 135 CHECK_NE(memptr, 0); 136 *memptr = MsanReallocate(&stack, 0, size, alignment, false); 137 CHECK_NE(*memptr, 0); 138 __msan_unpoison(memptr, sizeof(*memptr)); 139 return 0; 140} 141 142INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) { 143 GET_MALLOC_STACK_TRACE; 144 CHECK_EQ(boundary & (boundary - 1), 0); 145 void *ptr = MsanReallocate(&stack, 0, size, boundary, false); 146 return ptr; 147} 148 149INTERCEPTOR(void *, valloc, SIZE_T size) { 150 GET_MALLOC_STACK_TRACE; 151 void *ptr = MsanReallocate(&stack, 0, size, GetPageSizeCached(), false); 152 return ptr; 153} 154 155INTERCEPTOR(void *, pvalloc, SIZE_T size) { 156 GET_MALLOC_STACK_TRACE; 157 uptr PageSize = GetPageSizeCached(); 158 size = RoundUpTo(size, PageSize); 159 if (size == 0) { 160 // pvalloc(0) should allocate one page. 161 size = PageSize; 162 } 163 void *ptr = MsanReallocate(&stack, 0, size, PageSize, false); 164 return ptr; 165} 166 167INTERCEPTOR(void, free, void *ptr) { 168 ENSURE_MSAN_INITED(); 169 if (ptr == 0) return; 170 MsanDeallocate(ptr); 171} 172 173INTERCEPTOR(SIZE_T, strlen, const char *s) { 174 ENSURE_MSAN_INITED(); 175 SIZE_T res = REAL(strlen)(s); 176 CHECK_UNPOISONED(s, res + 1); 177 return res; 178} 179 180INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) { 181 ENSURE_MSAN_INITED(); 182 SIZE_T res = REAL(strnlen)(s, n); 183 SIZE_T scan_size = (res == n) ? res : res + 1; 184 CHECK_UNPOISONED(s, scan_size); 185 return res; 186} 187 188// FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should 189// check the shadow of the terminating \0 byte). 190 191INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT 192 ENSURE_MSAN_INITED(); 193 SIZE_T n = REAL(strlen)(src); 194 char *res = REAL(strcpy)(dest, src); // NOLINT 195 __msan_copy_poison(dest, src, n + 1); 196 return res; 197} 198 199INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT 200 ENSURE_MSAN_INITED(); 201 SIZE_T copy_size = REAL(strnlen)(src, n); 202 if (copy_size < n) 203 copy_size++; // trailing \0 204 char *res = REAL(strncpy)(dest, src, n); // NOLINT 205 __msan_copy_poison(dest, src, copy_size); 206 return res; 207} 208 209INTERCEPTOR(char *, stpcpy, char *dest, const char *src) { // NOLINT 210 ENSURE_MSAN_INITED(); 211 SIZE_T n = REAL(strlen)(src); 212 char *res = REAL(stpcpy)(dest, src); // NOLINT 213 __msan_copy_poison(dest, src, n + 1); 214 return res; 215} 216 217INTERCEPTOR(char *, strdup, char *src) { 218 ENSURE_MSAN_INITED(); 219 SIZE_T n = REAL(strlen)(src); 220 char *res = REAL(strdup)(src); 221 __msan_copy_poison(res, src, n + 1); 222 return res; 223} 224 225INTERCEPTOR(char *, __strdup, char *src) { 226 ENSURE_MSAN_INITED(); 227 SIZE_T n = REAL(strlen)(src); 228 char *res = REAL(__strdup)(src); 229 __msan_copy_poison(res, src, n + 1); 230 return res; 231} 232 233INTERCEPTOR(char *, strndup, char *src, SIZE_T n) { 234 ENSURE_MSAN_INITED(); 235 SIZE_T copy_size = REAL(strnlen)(src, n); 236 char *res = REAL(strndup)(src, n); 237 __msan_copy_poison(res, src, copy_size); 238 __msan_unpoison(res + copy_size, 1); // \0 239 return res; 240} 241 242INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) { 243 ENSURE_MSAN_INITED(); 244 SIZE_T copy_size = REAL(strnlen)(src, n); 245 char *res = REAL(__strndup)(src, n); 246 __msan_copy_poison(res, src, copy_size); 247 __msan_unpoison(res + copy_size, 1); // \0 248 return res; 249} 250 251INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { 252 ENSURE_MSAN_INITED(); 253 char *res = REAL(gcvt)(number, ndigit, buf); 254 // DynamoRio tool will take care of unpoisoning gcvt result for us. 255 if (!__msan_has_dynamic_component()) { 256 SIZE_T n = REAL(strlen)(buf); 257 __msan_unpoison(buf, n + 1); 258 } 259 return res; 260} 261 262INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT 263 ENSURE_MSAN_INITED(); 264 SIZE_T src_size = REAL(strlen)(src); 265 SIZE_T dest_size = REAL(strlen)(dest); 266 char *res = REAL(strcat)(dest, src); // NOLINT 267 __msan_copy_poison(dest + dest_size, src, src_size + 1); 268 return res; 269} 270 271INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT 272 ENSURE_MSAN_INITED(); 273 SIZE_T dest_size = REAL(strlen)(dest); 274 SIZE_T copy_size = REAL(strlen)(src); 275 if (copy_size < n) 276 copy_size++; // trailing \0 277 char *res = REAL(strncat)(dest, src, n); // NOLINT 278 __msan_copy_poison(dest + dest_size, src, copy_size); 279 return res; 280} 281 282INTERCEPTOR(long, strtol, const char *nptr, char **endptr, // NOLINT 283 int base) { 284 ENSURE_MSAN_INITED(); 285 long res = REAL(strtol)(nptr, endptr, base); // NOLINT 286 if (!__msan_has_dynamic_component()) { 287 __msan_unpoison(endptr, sizeof(*endptr)); 288 } 289 return res; 290} 291 292INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, // NOLINT 293 int base) { 294 ENSURE_MSAN_INITED(); 295 long res = REAL(strtoll)(nptr, endptr, base); //NOLINT 296 if (!__msan_has_dynamic_component()) { 297 __msan_unpoison(endptr, sizeof(*endptr)); 298 } 299 return res; 300} 301 302INTERCEPTOR(unsigned long, strtoul, const char *nptr, char **endptr, // NOLINT 303 int base) { 304 ENSURE_MSAN_INITED(); 305 unsigned long res = REAL(strtoul)(nptr, endptr, base); // NOLINT 306 if (!__msan_has_dynamic_component()) { 307 __msan_unpoison(endptr, sizeof(*endptr)); 308 } 309 return res; 310} 311 312INTERCEPTOR(unsigned long long, strtoull, const char *nptr, // NOLINT 313 char **endptr, int base) { 314 ENSURE_MSAN_INITED(); 315 unsigned long res = REAL(strtoull)(nptr, endptr, base); // NOLINT 316 if (!__msan_has_dynamic_component()) { 317 __msan_unpoison(endptr, sizeof(*endptr)); 318 } 319 return res; 320} 321 322INTERCEPTOR(double, strtod, const char *nptr, char **endptr) { // NOLINT 323 ENSURE_MSAN_INITED(); 324 double res = REAL(strtod)(nptr, endptr); // NOLINT 325 if (!__msan_has_dynamic_component()) { 326 __msan_unpoison(endptr, sizeof(*endptr)); 327 } 328 return res; 329} 330 331INTERCEPTOR(float, strtof, const char *nptr, char **endptr) { // NOLINT 332 ENSURE_MSAN_INITED(); 333 float res = REAL(strtof)(nptr, endptr); // NOLINT 334 if (!__msan_has_dynamic_component()) { 335 __msan_unpoison(endptr, sizeof(*endptr)); 336 } 337 return res; 338} 339 340INTERCEPTOR(long double, strtold, const char *nptr, char **endptr) { // NOLINT 341 ENSURE_MSAN_INITED(); 342 long double res = REAL(strtold)(nptr, endptr); // NOLINT 343 if (!__msan_has_dynamic_component()) { 344 __msan_unpoison(endptr, sizeof(*endptr)); 345 } 346 return res; 347} 348 349INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) { 350 ENSURE_MSAN_INITED(); 351 int res = REAL(vasprintf)(strp, format, ap); 352 if (res >= 0 && !__msan_has_dynamic_component()) { 353 __msan_unpoison(strp, sizeof(*strp)); 354 __msan_unpoison(*strp, res + 1); 355 } 356 return res; 357} 358 359INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) { // NOLINT 360 ENSURE_MSAN_INITED(); 361 va_list ap; 362 va_start(ap, format); 363 int res = vasprintf(strp, format, ap); // NOLINT 364 va_end(ap); 365 return res; 366} 367 368INTERCEPTOR(int, vsnprintf, char *str, uptr size, 369 const char *format, va_list ap) { 370 ENSURE_MSAN_INITED(); 371 int res = REAL(vsnprintf)(str, size, format, ap); 372 if (res >= 0 && !__msan_has_dynamic_component()) { 373 __msan_unpoison(str, res + 1); 374 } 375 return res; 376} 377 378INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) { 379 ENSURE_MSAN_INITED(); 380 int res = REAL(vsprintf)(str, format, ap); 381 if (res >= 0 && !__msan_has_dynamic_component()) { 382 __msan_unpoison(str, res + 1); 383 } 384 return res; 385} 386 387INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) { 388 ENSURE_MSAN_INITED(); 389 int res = REAL(vswprintf)(str, size, format, ap); 390 if (res >= 0 && !__msan_has_dynamic_component()) { 391 __msan_unpoison(str, 4 * (res + 1)); 392 } 393 return res; 394} 395 396INTERCEPTOR(int, sprintf, char *str, const char *format, ...) { // NOLINT 397 ENSURE_MSAN_INITED(); 398 va_list ap; 399 va_start(ap, format); 400 int res = vsprintf(str, format, ap); // NOLINT 401 va_end(ap); 402 return res; 403} 404 405INTERCEPTOR(int, snprintf, char *str, uptr size, const char *format, ...) { 406 ENSURE_MSAN_INITED(); 407 va_list ap; 408 va_start(ap, format); 409 int res = vsnprintf(str, size, format, ap); 410 va_end(ap); 411 return res; 412} 413 414INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) { 415 ENSURE_MSAN_INITED(); 416 va_list ap; 417 va_start(ap, format); 418 int res = vswprintf(str, size, format, ap); 419 va_end(ap); 420 return res; 421} 422 423// SIZE_T strftime(char *s, SIZE_T max, const char *format,const struct tm *tm); 424INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format, 425 void *tm) { 426 ENSURE_MSAN_INITED(); 427 SIZE_T res = REAL(strftime)(s, max, format, tm); 428 if (res) __msan_unpoison(s, res + 1); 429 return res; 430} 431 432INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) { 433 ENSURE_MSAN_INITED(); 434 int res = REAL(mbtowc)(dest, src, n); 435 if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 436 return res; 437} 438 439INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) { 440 ENSURE_MSAN_INITED(); 441 SIZE_T res = REAL(mbrtowc)(dest, src, n, ps); 442 if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t)); 443 return res; 444} 445 446INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { 447 ENSURE_MSAN_INITED(); 448 SIZE_T res = REAL(wcslen)(s); 449 CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1)); 450 return res; 451} 452 453// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); 454INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { 455 ENSURE_MSAN_INITED(); 456 wchar_t *res = REAL(wcschr)(s, wc, ps); 457 return res; 458} 459 460// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); 461INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { 462 ENSURE_MSAN_INITED(); 463 wchar_t *res = REAL(wcscpy)(dest, src); 464 __msan_copy_poison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1)); 465 return res; 466} 467 468// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n); 469INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 470 ENSURE_MSAN_INITED(); 471 wchar_t *res = REAL(wmemcpy)(dest, src, n); 472 __msan_copy_poison(dest, src, n * sizeof(wchar_t)); 473 return res; 474} 475 476INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 477 ENSURE_MSAN_INITED(); 478 wchar_t *res = REAL(wmempcpy)(dest, src, n); 479 __msan_copy_poison(dest, src, n * sizeof(wchar_t)); 480 return res; 481} 482 483INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) { 484 CHECK(MEM_IS_APP(s)); 485 ENSURE_MSAN_INITED(); 486 wchar_t *res = (wchar_t *)fast_memset(s, c, n * sizeof(wchar_t)); 487 __msan_unpoison(s, n * sizeof(wchar_t)); 488 return res; 489} 490 491INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) { 492 ENSURE_MSAN_INITED(); 493 wchar_t *res = REAL(wmemmove)(dest, src, n); 494 __msan_move_poison(dest, src, n * sizeof(wchar_t)); 495 return res; 496} 497 498INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) { 499 ENSURE_MSAN_INITED(); 500 int res = REAL(wcscmp)(s1, s2); 501 return res; 502} 503 504INTERCEPTOR(double, wcstod, const wchar_t *nptr, wchar_t **endptr) { 505 ENSURE_MSAN_INITED(); 506 double res = REAL(wcstod)(nptr, endptr); 507 __msan_unpoison(endptr, sizeof(*endptr)); 508 return res; 509} 510 511// #define UNSUPPORTED(name) \ 512// INTERCEPTOR(void, name, void) { \ 513// Printf("MSAN: Unsupported %s\n", __FUNCTION__); \ 514// Die(); \ 515// } 516 517// FIXME: intercept the following functions: 518// Note, they only matter when running without a dynamic tool. 519// UNSUPPORTED(wcscoll_l) 520// UNSUPPORTED(wcsnrtombs) 521// UNSUPPORTED(wcstol) 522// UNSUPPORTED(wcstoll) 523// UNSUPPORTED(wcstold) 524// UNSUPPORTED(wcstoul) 525// UNSUPPORTED(wcstoull) 526// UNSUPPORTED(wcsxfrm_l) 527// UNSUPPORTED(wcsdup) 528// UNSUPPORTED(wcsftime) 529// UNSUPPORTED(wcsstr) 530// UNSUPPORTED(wcsrchr) 531// UNSUPPORTED(wctob) 532 533INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { 534 ENSURE_MSAN_INITED(); 535 int res = REAL(gettimeofday)(tv, tz); 536 if (tv) 537 __msan_unpoison(tv, 16); 538 if (tz) 539 __msan_unpoison(tz, 8); 540 return res; 541} 542 543INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) { 544 ENSURE_MSAN_INITED(); 545 char *res = REAL(fcvt)(x, a, b, c); 546 if (!__msan_has_dynamic_component()) { 547 __msan_unpoison(b, sizeof(*b)); 548 __msan_unpoison(c, sizeof(*c)); 549 } 550 return res; 551} 552 553INTERCEPTOR(char *, getenv, char *name) { 554 ENSURE_MSAN_INITED(); 555 char *res = REAL(getenv)(name); 556 if (!__msan_has_dynamic_component()) { 557 if (res) 558 __msan_unpoison(res, REAL(strlen)(res) + 1); 559 } 560 return res; 561} 562 563extern char **environ; 564 565static void UnpoisonEnviron() { 566 char **envp = environ; 567 for (; *envp; ++envp) { 568 __msan_unpoison(envp, sizeof(*envp)); 569 __msan_unpoison(*envp, REAL(strlen)(*envp) + 1); 570 } 571 // Trailing NULL pointer. 572 __msan_unpoison(envp, sizeof(*envp)); 573} 574 575INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) { 576 ENSURE_MSAN_INITED(); 577 int res = REAL(setenv)(name, value, overwrite); 578 if (!res) UnpoisonEnviron(); 579 return res; 580} 581 582INTERCEPTOR(int, putenv, char *string) { 583 ENSURE_MSAN_INITED(); 584 int res = REAL(putenv)(string); 585 if (!res) UnpoisonEnviron(); 586 return res; 587} 588 589INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { 590 ENSURE_MSAN_INITED(); 591 int res = REAL(__fxstat)(magic, fd, buf); 592 if (!res) 593 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 594 return res; 595} 596 597INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { 598 ENSURE_MSAN_INITED(); 599 int res = REAL(__fxstat64)(magic, fd, buf); 600 if (!res) 601 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 602 return res; 603} 604 605INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) { 606 ENSURE_MSAN_INITED(); 607 int res = REAL(__xstat)(magic, path, buf); 608 if (!res) 609 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 610 return res; 611} 612 613INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) { 614 ENSURE_MSAN_INITED(); 615 int res = REAL(__xstat64)(magic, path, buf); 616 if (!res) 617 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 618 return res; 619} 620 621INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) { 622 ENSURE_MSAN_INITED(); 623 int res = REAL(__lxstat)(magic, path, buf); 624 if (!res) 625 __msan_unpoison(buf, __sanitizer::struct_stat_sz); 626 return res; 627} 628 629INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) { 630 ENSURE_MSAN_INITED(); 631 int res = REAL(__lxstat64)(magic, path, buf); 632 if (!res) 633 __msan_unpoison(buf, __sanitizer::struct_stat64_sz); 634 return res; 635} 636 637INTERCEPTOR(int, pipe, int pipefd[2]) { 638 if (msan_init_is_running) 639 return REAL(pipe)(pipefd); 640 ENSURE_MSAN_INITED(); 641 int res = REAL(pipe)(pipefd); 642 if (!res) 643 __msan_unpoison(pipefd, sizeof(int[2])); 644 return res; 645} 646 647INTERCEPTOR(int, pipe2, int pipefd[2], int flags) { 648 ENSURE_MSAN_INITED(); 649 int res = REAL(pipe2)(pipefd, flags); 650 if (!res) 651 __msan_unpoison(pipefd, sizeof(int[2])); 652 return res; 653} 654 655INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) { 656 ENSURE_MSAN_INITED(); 657 int res = REAL(socketpair)(domain, type, protocol, sv); 658 if (!res) 659 __msan_unpoison(sv, sizeof(int[2])); 660 return res; 661} 662 663INTERCEPTOR(char *, fgets, char *s, int size, void *stream) { 664 ENSURE_MSAN_INITED(); 665 char *res = REAL(fgets)(s, size, stream); 666 if (res) 667 __msan_unpoison(s, REAL(strlen)(s) + 1); 668 return res; 669} 670 671INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { 672 ENSURE_MSAN_INITED(); 673 char *res = REAL(fgets_unlocked)(s, size, stream); 674 if (res) 675 __msan_unpoison(s, REAL(strlen)(s) + 1); 676 return res; 677} 678 679INTERCEPTOR(int, getrlimit, int resource, void *rlim) { 680 if (msan_init_is_running) 681 return REAL(getrlimit)(resource, rlim); 682 ENSURE_MSAN_INITED(); 683 int res = REAL(getrlimit)(resource, rlim); 684 if (!res) 685 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); 686 return res; 687} 688 689INTERCEPTOR(int, getrlimit64, int resource, void *rlim) { 690 if (msan_init_is_running) 691 return REAL(getrlimit64)(resource, rlim); 692 ENSURE_MSAN_INITED(); 693 int res = REAL(getrlimit64)(resource, rlim); 694 if (!res) 695 __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz); 696 return res; 697} 698 699INTERCEPTOR(int, statfs, const char *s, void *buf) { 700 ENSURE_MSAN_INITED(); 701 int res = REAL(statfs)(s, buf); 702 if (!res) 703 __msan_unpoison(buf, __sanitizer::struct_statfs_sz); 704 return res; 705} 706 707INTERCEPTOR(int, fstatfs, int fd, void *buf) { 708 ENSURE_MSAN_INITED(); 709 int res = REAL(fstatfs)(fd, buf); 710 if (!res) 711 __msan_unpoison(buf, __sanitizer::struct_statfs_sz); 712 return res; 713} 714 715INTERCEPTOR(int, statfs64, const char *s, void *buf) { 716 ENSURE_MSAN_INITED(); 717 int res = REAL(statfs64)(s, buf); 718 if (!res) 719 __msan_unpoison(buf, __sanitizer::struct_statfs64_sz); 720 return res; 721} 722 723INTERCEPTOR(int, fstatfs64, int fd, void *buf) { 724 ENSURE_MSAN_INITED(); 725 int res = REAL(fstatfs64)(fd, buf); 726 if (!res) 727 __msan_unpoison(buf, __sanitizer::struct_statfs64_sz); 728 return res; 729} 730 731INTERCEPTOR(int, uname, void *utsname) { 732 ENSURE_MSAN_INITED(); 733 int res = REAL(uname)(utsname); 734 if (!res) { 735 __msan_unpoison(utsname, __sanitizer::struct_utsname_sz); 736 } 737 return res; 738} 739 740INTERCEPTOR(int, gethostname, char *name, SIZE_T len) { 741 ENSURE_MSAN_INITED(); 742 int res = REAL(gethostname)(name, len); 743 if (!res) { 744 SIZE_T real_len = REAL(strnlen)(name, len); 745 if (real_len < len) 746 ++real_len; 747 __msan_unpoison(name, real_len); 748 } 749 return res; 750} 751 752INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents, 753 int timeout) { 754 ENSURE_MSAN_INITED(); 755 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout); 756 if (res > 0) { 757 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 758 } 759 return res; 760} 761 762INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, 763 int timeout, void *sigmask) { 764 ENSURE_MSAN_INITED(); 765 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask); 766 if (res > 0) { 767 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res); 768 } 769 return res; 770} 771 772INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { 773 ENSURE_MSAN_INITED(); 774 SSIZE_T res = REAL(recv)(fd, buf, len, flags); 775 if (res > 0) 776 __msan_unpoison(buf, res); 777 return res; 778} 779 780INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, 781 void *srcaddr, int *addrlen) { 782 ENSURE_MSAN_INITED(); 783 SIZE_T srcaddr_sz; 784 if (srcaddr) srcaddr_sz = *addrlen; 785 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); 786 if (res > 0) { 787 __msan_unpoison(buf, res); 788 if (srcaddr) { 789 SIZE_T sz = *addrlen; 790 __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz); 791 } 792 } 793 return res; 794} 795 796INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { 797 if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0; 798 GET_MALLOC_STACK_TRACE; 799 if (!msan_inited) { 800 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 801 const SIZE_T kCallocPoolSize = 1024; 802 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 803 static SIZE_T allocated; 804 SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 805 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 806 allocated += size_in_words; 807 CHECK(allocated < kCallocPoolSize); 808 return mem; 809 } 810 return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true); 811} 812 813INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { 814 GET_MALLOC_STACK_TRACE; 815 return MsanReallocate(&stack, ptr, size, sizeof(u64), false); 816} 817 818INTERCEPTOR(void *, malloc, SIZE_T size) { 819 GET_MALLOC_STACK_TRACE; 820 return MsanReallocate(&stack, 0, size, sizeof(u64), false); 821} 822 823void __msan_allocated_memory(const void* data, uptr size) { 824 GET_MALLOC_STACK_TRACE; 825 if (flags()->poison_in_malloc) 826 __msan_poison(data, size); 827 if (__msan_get_track_origins()) { 828 u32 stack_id = StackDepotPut(stack.trace, stack.size); 829 CHECK(stack_id); 830 CHECK_EQ((stack_id >> 31), 0); // Higher bit is occupied by stack origins. 831 __msan_set_origin(data, size, stack_id); 832 } 833} 834 835INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, 836 int fd, OFF_T offset) { 837 ENSURE_MSAN_INITED(); 838 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset); 839 if (res != (void*)-1) 840 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 841 return res; 842} 843 844INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, 845 int fd, OFF64_T offset) { 846 ENSURE_MSAN_INITED(); 847 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset); 848 if (res != (void*)-1) 849 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 850 return res; 851} 852 853struct dlinfo { 854 char *dli_fname; 855 void *dli_fbase; 856 char *dli_sname; 857 void *dli_saddr; 858}; 859 860INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { 861 ENSURE_MSAN_INITED(); 862 int res = REAL(dladdr)(addr, info); 863 if (res != 0) { 864 __msan_unpoison(info, sizeof(*info)); 865 if (info->dli_fname) 866 __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); 867 if (info->dli_sname) 868 __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); 869 } 870 return res; 871} 872 873// dlopen() ultimately calls mmap() down inside the loader, which generally 874// doesn't participate in dynamic symbol resolution. Therefore we won't 875// intercept its calls to mmap, and we have to hook it here. The loader 876// initializes the module before returning, so without the dynamic component, we 877// won't be able to clear the shadow before the initializers. Fixing this would 878// require putting our own initializer first to clear the shadow. 879INTERCEPTOR(void *, dlopen, const char *filename, int flag) { 880 ENSURE_MSAN_INITED(); 881 EnterLoader(); 882 link_map *map = (link_map *)REAL(dlopen)(filename, flag); 883 ExitLoader(); 884 if (!__msan_has_dynamic_component() && map) { 885 // If msandr didn't clear the shadow before the initializers ran, we do it 886 // ourselves afterwards. 887 ForEachMappedRegion(map, __msan_unpoison); 888 } 889 return (void *)map; 890} 891 892typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, 893 void *data); 894struct dl_iterate_phdr_data { 895 dl_iterate_phdr_cb callback; 896 void *data; 897}; 898 899static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, 900 void *data) { 901 if (info) { 902 __msan_unpoison(info, size); 903 if (info->dlpi_name) 904 __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); 905 } 906 dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; 907 UnpoisonParam(3); 908 return cbdata->callback(info, size, cbdata->data); 909} 910 911INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { 912 ENSURE_MSAN_INITED(); 913 EnterLoader(); 914 dl_iterate_phdr_data cbdata; 915 cbdata.callback = callback; 916 cbdata.data = data; 917 int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); 918 ExitLoader(); 919 return res; 920} 921 922INTERCEPTOR(int, getrusage, int who, void *usage) { 923 ENSURE_MSAN_INITED(); 924 int res = REAL(getrusage)(who, usage); 925 if (res == 0) { 926 __msan_unpoison(usage, __sanitizer::struct_rusage_sz); 927 } 928 return res; 929} 930 931// sigactions_mu guarantees atomicity of sigaction() and signal() calls. 932// Access to sigactions[] is gone with relaxed atomics to avoid data race with 933// the signal handler. 934const int kMaxSignals = 1024; 935static atomic_uintptr_t sigactions[kMaxSignals]; 936static StaticSpinMutex sigactions_mu; 937 938static void SignalHandler(int signo) { 939 ScopedThreadLocalStateBackup stlsb; 940 UnpoisonParam(1); 941 942 typedef void (*signal_cb)(int x); 943 signal_cb cb = 944 (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 945 cb(signo); 946} 947 948static void SignalAction(int signo, void *si, void *uc) { 949 ScopedThreadLocalStateBackup stlsb; 950 UnpoisonParam(3); 951 __msan_unpoison(si, sizeof(__sanitizer_sigaction)); 952 __msan_unpoison(uc, __sanitizer::ucontext_t_sz); 953 954 typedef void (*sigaction_cb)(int, void *, void *); 955 sigaction_cb cb = 956 (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); 957 cb(signo, si, uc); 958} 959 960INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, 961 __sanitizer_sigaction *oldact) { 962 ENSURE_MSAN_INITED(); 963 // FIXME: check that *act is unpoisoned. 964 // That requires intercepting all of sigemptyset, sigfillset, etc. 965 int res; 966 if (flags()->wrap_signals) { 967 SpinMutexLock lock(&sigactions_mu); 968 CHECK_LT(signo, kMaxSignals); 969 uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); 970 __sanitizer_sigaction new_act; 971 __sanitizer_sigaction *pnew_act = act ? &new_act : 0; 972 if (act) { 973 internal_memcpy(pnew_act, act, sizeof(__sanitizer_sigaction)); 974 uptr cb = (uptr)pnew_act->sa_sigaction; 975 uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo) 976 ? (uptr)SignalAction 977 : (uptr)SignalHandler; 978 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 979 atomic_store(&sigactions[signo], cb, memory_order_relaxed); 980 pnew_act->sa_sigaction = (void (*)(int, void *, void *))new_cb; 981 } 982 } 983 res = REAL(sigaction)(signo, pnew_act, oldact); 984 if (res == 0 && oldact) { 985 uptr cb = (uptr)oldact->sa_sigaction; 986 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 987 oldact->sa_sigaction = (void (*)(int, void *, void *))old_cb; 988 } 989 } 990 } else { 991 res = REAL(sigaction)(signo, act, oldact); 992 } 993 994 if (res == 0 && oldact) { 995 __msan_unpoison(oldact, sizeof(__sanitizer_sigaction)); 996 } 997 return res; 998} 999 1000INTERCEPTOR(int, signal, int signo, uptr cb) { 1001 ENSURE_MSAN_INITED(); 1002 if (flags()->wrap_signals) { 1003 CHECK_LT(signo, kMaxSignals); 1004 SpinMutexLock lock(&sigactions_mu); 1005 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { 1006 atomic_store(&sigactions[signo], cb, memory_order_relaxed); 1007 cb = (uptr) SignalHandler; 1008 } 1009 return REAL(signal)(signo, cb); 1010 } else { 1011 return REAL(signal)(signo, cb); 1012 } 1013} 1014 1015extern "C" int pthread_attr_init(void *attr); 1016extern "C" int pthread_attr_destroy(void *attr); 1017extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); 1018extern "C" int pthread_attr_getstack(void *attr, uptr *stack, uptr *stacksize); 1019 1020INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), 1021 void * param) { 1022 ENSURE_MSAN_INITED(); // for GetTlsSize() 1023 __sanitizer_pthread_attr_t myattr; 1024 if (attr == 0) { 1025 pthread_attr_init(&myattr); 1026 attr = &myattr; 1027 } 1028 1029 AdjustStackSizeLinux(attr, flags()->verbosity); 1030 1031 int res = REAL(pthread_create)(th, attr, callback, param); 1032 if (attr == &myattr) 1033 pthread_attr_destroy(&myattr); 1034 if (!res) { 1035 __msan_unpoison(th, __sanitizer::pthread_t_sz); 1036 } 1037 return res; 1038} 1039 1040INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key, 1041 void (*dtor)(void *value)) { 1042 ENSURE_MSAN_INITED(); 1043 int res = REAL(pthread_key_create)(key, dtor); 1044 if (!res && key) 1045 __msan_unpoison(key, sizeof(*key)); 1046 return res; 1047} 1048 1049INTERCEPTOR(int, pthread_join, void *th, void **retval) { 1050 ENSURE_MSAN_INITED(); 1051 int res = REAL(pthread_join)(th, retval); 1052 if (!res && retval) 1053 __msan_unpoison(retval, sizeof(*retval)); 1054 return res; 1055} 1056 1057struct MSanInterceptorContext { 1058 bool in_interceptor_scope; 1059}; 1060 1061// A version of CHECK_UNPOISED using a saved scope value. Used in common 1062// interceptors. 1063#define CHECK_UNPOISONED_CTX(ctx, x, n) \ 1064 do { \ 1065 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \ 1066 CHECK_UNPOISONED_0(x, n); \ 1067 } while (0) 1068 1069#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ 1070 UnpoisonParam(count) 1071#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 1072 __msan_unpoison(ptr, size) 1073#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 1074 CHECK_UNPOISONED_CTX(ctx, ptr, size) 1075#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 1076 if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \ 1077 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \ 1078 ctx = (void *)&msan_ctx; \ 1079 InterceptorScope interceptor_scope; \ 1080 ENSURE_MSAN_INITED(); 1081#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 1082 do { \ 1083 } while (false) 1084#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 1085 do { \ 1086 } while (false) 1087#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 1088 do { \ 1089 } while (false) 1090#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ 1091 do { \ 1092 } while (false) // FIXME 1093#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 1094#include "sanitizer_common/sanitizer_common_interceptors.inc" 1095 1096#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) 1097#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) 1098#define COMMON_SYSCALL_POST_READ_RANGE(p, s) 1099#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s) 1100#include "sanitizer_common/sanitizer_common_syscalls.inc" 1101 1102// static 1103void *fast_memset(void *ptr, int c, SIZE_T n) { 1104 // hack until we have a really fast internal_memset 1105 if (sizeof(uptr) == 8 && 1106 (n % 8) == 0 && 1107 ((uptr)ptr % 8) == 0 && 1108 (c == 0 || c == -1)) { 1109 // Printf("memset %p %zd %x\n", ptr, n, c); 1110 uptr to_store = c ? -1L : 0L; 1111 uptr *p = (uptr*)ptr; 1112 for (SIZE_T i = 0; i < n / 8; i++) 1113 p[i] = to_store; 1114 return ptr; 1115 } 1116 return internal_memset(ptr, c, n); 1117} 1118 1119// static 1120void *fast_memcpy(void *dst, const void *src, SIZE_T n) { 1121 // Same hack as in fast_memset above. 1122 if (sizeof(uptr) == 8 && 1123 (n % 8) == 0 && 1124 ((uptr)dst % 8) == 0 && 1125 ((uptr)src % 8) == 0) { 1126 uptr *d = (uptr*)dst; 1127 uptr *s = (uptr*)src; 1128 for (SIZE_T i = 0; i < n / 8; i++) 1129 d[i] = s[i]; 1130 return dst; 1131 } 1132 return internal_memcpy(dst, src, n); 1133} 1134 1135// These interface functions reside here so that they can use 1136// fast_memset, etc. 1137void __msan_unpoison(const void *a, uptr size) { 1138 if (!MEM_IS_APP(a)) return; 1139 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size); 1140} 1141 1142void __msan_poison(const void *a, uptr size) { 1143 if (!MEM_IS_APP(a)) return; 1144 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 1145 __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size); 1146} 1147 1148void __msan_poison_stack(void *a, uptr size) { 1149 if (!MEM_IS_APP(a)) return; 1150 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 1151 __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size); 1152} 1153 1154void __msan_clear_and_unpoison(void *a, uptr size) { 1155 fast_memset(a, 0, size); 1156 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size); 1157} 1158 1159void __msan_copy_origin(void *dst, const void *src, uptr size) { 1160 if (!__msan_get_track_origins()) return; 1161 if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return; 1162 uptr d = MEM_TO_ORIGIN(dst); 1163 uptr s = MEM_TO_ORIGIN(src); 1164 uptr beg = d & ~3UL; // align down. 1165 uptr end = (d + size + 3) & ~3UL; // align up. 1166 s = s & ~3UL; // align down. 1167 fast_memcpy((void*)beg, (void*)s, end - beg); 1168} 1169 1170void __msan_copy_poison(void *dst, const void *src, uptr size) { 1171 if (!MEM_IS_APP(dst)) return; 1172 if (!MEM_IS_APP(src)) return; 1173 fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst), 1174 (void*)MEM_TO_SHADOW((uptr)src), size); 1175 __msan_copy_origin(dst, src, size); 1176} 1177 1178void __msan_move_poison(void *dst, const void *src, uptr size) { 1179 if (!MEM_IS_APP(dst)) return; 1180 if (!MEM_IS_APP(src)) return; 1181 internal_memmove((void*)MEM_TO_SHADOW((uptr)dst), 1182 (void*)MEM_TO_SHADOW((uptr)src), size); 1183 __msan_copy_origin(dst, src, size); 1184} 1185 1186void *__msan_memcpy(void *dest, const void *src, SIZE_T n) { 1187 ENSURE_MSAN_INITED(); 1188 void *res = fast_memcpy(dest, src, n); 1189 __msan_copy_poison(dest, src, n); 1190 return res; 1191} 1192 1193void *__msan_memset(void *s, int c, SIZE_T n) { 1194 ENSURE_MSAN_INITED(); 1195 void *res = fast_memset(s, c, n); 1196 __msan_unpoison(s, n); 1197 return res; 1198} 1199 1200void *__msan_memmove(void *dest, const void *src, SIZE_T n) { 1201 ENSURE_MSAN_INITED(); 1202 void *res = REAL(memmove)(dest, src, n); 1203 __msan_move_poison(dest, src, n); 1204 return res; 1205} 1206 1207namespace __msan { 1208void InitializeInterceptors() { 1209 static int inited = 0; 1210 CHECK_EQ(inited, 0); 1211 SANITIZER_COMMON_INTERCEPTORS_INIT; 1212 1213 INTERCEPT_FUNCTION(mmap); 1214 INTERCEPT_FUNCTION(mmap64); 1215 INTERCEPT_FUNCTION(posix_memalign); 1216 INTERCEPT_FUNCTION(memalign); 1217 INTERCEPT_FUNCTION(valloc); 1218 INTERCEPT_FUNCTION(pvalloc); 1219 INTERCEPT_FUNCTION(malloc); 1220 INTERCEPT_FUNCTION(calloc); 1221 INTERCEPT_FUNCTION(realloc); 1222 INTERCEPT_FUNCTION(free); 1223 INTERCEPT_FUNCTION(fread); 1224 INTERCEPT_FUNCTION(fread_unlocked); 1225 INTERCEPT_FUNCTION(readlink); 1226 INTERCEPT_FUNCTION(memcpy); 1227 INTERCEPT_FUNCTION(mempcpy); 1228 INTERCEPT_FUNCTION(memset); 1229 INTERCEPT_FUNCTION(memmove); 1230 INTERCEPT_FUNCTION(bcopy); 1231 INTERCEPT_FUNCTION(wmemset); 1232 INTERCEPT_FUNCTION(wmemcpy); 1233 INTERCEPT_FUNCTION(wmempcpy); 1234 INTERCEPT_FUNCTION(wmemmove); 1235 INTERCEPT_FUNCTION(strcpy); // NOLINT 1236 INTERCEPT_FUNCTION(stpcpy); // NOLINT 1237 INTERCEPT_FUNCTION(strdup); 1238 INTERCEPT_FUNCTION(__strdup); 1239 INTERCEPT_FUNCTION(strndup); 1240 INTERCEPT_FUNCTION(__strndup); 1241 INTERCEPT_FUNCTION(strncpy); // NOLINT 1242 INTERCEPT_FUNCTION(strlen); 1243 INTERCEPT_FUNCTION(strnlen); 1244 INTERCEPT_FUNCTION(gcvt); 1245 INTERCEPT_FUNCTION(strcat); // NOLINT 1246 INTERCEPT_FUNCTION(strncat); // NOLINT 1247 INTERCEPT_FUNCTION(strtol); 1248 INTERCEPT_FUNCTION(strtoll); 1249 INTERCEPT_FUNCTION(strtoul); 1250 INTERCEPT_FUNCTION(strtoull); 1251 INTERCEPT_FUNCTION(strtod); 1252 INTERCEPT_FUNCTION(strtof); 1253 INTERCEPT_FUNCTION(strtold); 1254 INTERCEPT_FUNCTION(vasprintf); 1255 INTERCEPT_FUNCTION(asprintf); 1256 INTERCEPT_FUNCTION(vsprintf); 1257 INTERCEPT_FUNCTION(vsnprintf); 1258 INTERCEPT_FUNCTION(vswprintf); 1259 INTERCEPT_FUNCTION(sprintf); // NOLINT 1260 INTERCEPT_FUNCTION(snprintf); 1261 INTERCEPT_FUNCTION(swprintf); 1262 INTERCEPT_FUNCTION(strftime); 1263 INTERCEPT_FUNCTION(mbtowc); 1264 INTERCEPT_FUNCTION(mbrtowc); 1265 INTERCEPT_FUNCTION(wcslen); 1266 INTERCEPT_FUNCTION(wcschr); 1267 INTERCEPT_FUNCTION(wcscpy); 1268 INTERCEPT_FUNCTION(wcscmp); 1269 INTERCEPT_FUNCTION(wcstod); 1270 INTERCEPT_FUNCTION(getenv); 1271 INTERCEPT_FUNCTION(setenv); 1272 INTERCEPT_FUNCTION(putenv); 1273 INTERCEPT_FUNCTION(gettimeofday); 1274 INTERCEPT_FUNCTION(fcvt); 1275 INTERCEPT_FUNCTION(__fxstat); 1276 INTERCEPT_FUNCTION(__xstat); 1277 INTERCEPT_FUNCTION(__lxstat); 1278 INTERCEPT_FUNCTION(__fxstat64); 1279 INTERCEPT_FUNCTION(__xstat64); 1280 INTERCEPT_FUNCTION(__lxstat64); 1281 INTERCEPT_FUNCTION(pipe); 1282 INTERCEPT_FUNCTION(pipe2); 1283 INTERCEPT_FUNCTION(socketpair); 1284 INTERCEPT_FUNCTION(fgets); 1285 INTERCEPT_FUNCTION(fgets_unlocked); 1286 INTERCEPT_FUNCTION(getrlimit); 1287 INTERCEPT_FUNCTION(getrlimit64); 1288 INTERCEPT_FUNCTION(statfs); 1289 INTERCEPT_FUNCTION(fstatfs); 1290 INTERCEPT_FUNCTION(statfs64); 1291 INTERCEPT_FUNCTION(fstatfs64); 1292 INTERCEPT_FUNCTION(uname); 1293 INTERCEPT_FUNCTION(gethostname); 1294 INTERCEPT_FUNCTION(epoll_wait); 1295 INTERCEPT_FUNCTION(epoll_pwait); 1296 INTERCEPT_FUNCTION(recv); 1297 INTERCEPT_FUNCTION(recvfrom); 1298 INTERCEPT_FUNCTION(dladdr); 1299 INTERCEPT_FUNCTION(dlopen); 1300 INTERCEPT_FUNCTION(dl_iterate_phdr); 1301 INTERCEPT_FUNCTION(getrusage); 1302 INTERCEPT_FUNCTION(sigaction); 1303 INTERCEPT_FUNCTION(signal); 1304 INTERCEPT_FUNCTION(pthread_create); 1305 INTERCEPT_FUNCTION(pthread_key_create); 1306 INTERCEPT_FUNCTION(pthread_join); 1307 inited = 1; 1308} 1309} // namespace __msan 1310