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