msan_interceptors.cc revision 9e6d3b3a9fa14a4f64df83303d562451b88ae11b
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 "msan_platform_limits_posix.h" 21#include "sanitizer_common/sanitizer_common.h" 22#include "sanitizer_common/sanitizer_libc.h" 23 24#include <stdarg.h> 25// ACHTUNG! No other system header includes in this file. 26// Ideally, we should get rid of stdarg.h as well. 27 28extern "C" const int __msan_keep_going; 29 30using namespace __msan; 31 32#define ENSURE_MSAN_INITED() do { \ 33 CHECK(!msan_init_is_running); \ 34 if (!msan_inited) { \ 35 __msan_init(); \ 36 } \ 37} while (0) 38 39#define CHECK_UNPOISONED(x, n) \ 40 do { \ 41 sptr offset = __msan_test_shadow(x, n); \ 42 if (offset >= 0 && flags()->report_umrs) { \ 43 GET_CALLER_PC_BP_SP; \ 44 (void)sp; \ 45 Printf("UMR in %s at offset %d inside [%p, +%d) \n", \ 46 __FUNCTION__, offset, x, n); \ 47 __msan::PrintWarningWithOrigin( \ 48 pc, bp, __msan_get_origin((char*)x + offset)); \ 49 if (!__msan_keep_going) { \ 50 Printf("Exiting\n"); \ 51 Die(); \ 52 } \ 53 } \ 54 } while (0) 55 56static void *fast_memset(void *ptr, int c, SIZE_T n); 57static void *fast_memcpy(void *dst, const void *src, SIZE_T n); 58 59INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) { 60 ENSURE_MSAN_INITED(); 61 SIZE_T res = REAL(fread)(ptr, size, nmemb, file); 62 if (res > 0) 63 __msan_unpoison(ptr, res *size); 64 return res; 65} 66 67INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb, 68 void *file) { 69 ENSURE_MSAN_INITED(); 70 SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file); 71 if (res > 0) 72 __msan_unpoison(ptr, res *size); 73 return res; 74} 75 76INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) { 77 ENSURE_MSAN_INITED(); 78 SSIZE_T res = REAL(readlink)(path, buf, bufsiz); 79 if (res > 0) 80 __msan_unpoison(buf, res); 81 return res; 82} 83 84INTERCEPTOR(void *, readdir, void *a) { 85 ENSURE_MSAN_INITED(); 86 void *res = REAL(readdir)(a); 87 __msan_unpoison(res, __msan::struct_dirent_sz); 88 return res; 89} 90 91INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) { 92 return __msan_memcpy(dest, src, n); 93} 94 95INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) { 96 return __msan_memmove(dest, src, n); 97} 98 99INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) { 100 return __msan_memset(s, c, n); 101} 102 103INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) { 104 GET_MALLOC_STACK_TRACE; 105 CHECK_EQ(alignment & (alignment - 1), 0); 106 *memptr = MsanReallocate(&stack, 0, size, alignment, false); 107 CHECK_NE(memptr, 0); 108 return 0; 109} 110 111INTERCEPTOR(void, free, void *ptr) { 112 ENSURE_MSAN_INITED(); 113 if (ptr == 0) return; 114 MsanDeallocate(ptr); 115} 116 117INTERCEPTOR(SIZE_T, strlen, const char *s) { 118 ENSURE_MSAN_INITED(); 119 SIZE_T res = REAL(strlen)(s); 120 CHECK_UNPOISONED(s, res + 1); 121 return res; 122} 123 124INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) { 125 ENSURE_MSAN_INITED(); 126 SIZE_T res = REAL(strnlen)(s, n); 127 SIZE_T scan_size = (res == n) ? res : res + 1; 128 CHECK_UNPOISONED(s, scan_size); 129 return res; 130} 131 132// FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should 133// check the shadow of the terminating \0 byte). 134 135INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT 136 ENSURE_MSAN_INITED(); 137 SIZE_T n = REAL(strlen)(src); 138 char *res = REAL(strcpy)(dest, src); // NOLINT 139 __msan_copy_poison(dest, src, n + 1); 140 return res; 141} 142 143INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT 144 ENSURE_MSAN_INITED(); 145 SIZE_T copy_size = REAL(strnlen)(src, n); 146 if (copy_size < n) 147 copy_size++; // trailing \0 148 char *res = REAL(strncpy)(dest, src, n); // NOLINT 149 __msan_copy_poison(dest, src, copy_size); 150 return res; 151} 152 153INTERCEPTOR(char *, strdup, char *src) { 154 ENSURE_MSAN_INITED(); 155 SIZE_T n = REAL(strlen)(src); 156 char *res = REAL(strdup)(src); 157 __msan_copy_poison(res, src, n + 1); 158 return res; 159} 160 161INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { 162 ENSURE_MSAN_INITED(); 163 char *res = REAL(gcvt)(number, ndigit, buf); 164 // DynamoRio tool will take care of unpoisoning gcvt result for us. 165 if (!__msan_has_dynamic_component()) { 166 SIZE_T n = REAL(strlen)(buf); 167 __msan_unpoison(buf, n + 1); 168 } 169 return res; 170} 171 172INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT 173 ENSURE_MSAN_INITED(); 174 SIZE_T src_size = REAL(strlen)(src); 175 SIZE_T dest_size = REAL(strlen)(dest); 176 char *res = REAL(strcat)(dest, src); // NOLINT 177 __msan_copy_poison(dest + dest_size, src, src_size + 1); 178 return res; 179} 180 181INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT 182 ENSURE_MSAN_INITED(); 183 SIZE_T dest_size = REAL(strlen)(dest); 184 SIZE_T copy_size = REAL(strlen)(src); 185 if (copy_size < n) 186 copy_size++; // trailing \0 187 char *res = REAL(strncat)(dest, src, n); // NOLINT 188 __msan_copy_poison(dest + dest_size, src, copy_size); 189 return res; 190} 191 192INTERCEPTOR(long, strtol, const char *nptr, char **endptr, // NOLINT 193 int base) { 194 ENSURE_MSAN_INITED(); 195 long res = REAL(strtol)(nptr, endptr, base); // NOLINT 196 if (!__msan_has_dynamic_component()) { 197 __msan_unpoison(endptr, sizeof(*endptr)); 198 } 199 return res; 200} 201 202INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, // NOLINT 203 int base) { 204 ENSURE_MSAN_INITED(); 205 long res = REAL(strtoll)(nptr, endptr, base); //NOLINT 206 if (!__msan_has_dynamic_component()) { 207 __msan_unpoison(endptr, sizeof(*endptr)); 208 } 209 return res; 210} 211 212INTERCEPTOR(unsigned long, strtoul, const char *nptr, char **endptr, // NOLINT 213 int base) { 214 ENSURE_MSAN_INITED(); 215 unsigned long res = REAL(strtoul)(nptr, endptr, base); // NOLINT 216 if (!__msan_has_dynamic_component()) { 217 __msan_unpoison(endptr, sizeof(*endptr)); 218 } 219 return res; 220} 221 222INTERCEPTOR(unsigned long long, strtoull, const char *nptr, // NOLINT 223 char **endptr, int base) { 224 ENSURE_MSAN_INITED(); 225 unsigned long res = REAL(strtoull)(nptr, endptr, base); // NOLINT 226 if (!__msan_has_dynamic_component()) { 227 __msan_unpoison(endptr, sizeof(*endptr)); 228 } 229 return res; 230} 231 232INTERCEPTOR(double, strtod, const char *nptr, char **endptr) { // NOLINT 233 ENSURE_MSAN_INITED(); 234 double res = REAL(strtod)(nptr, endptr); // NOLINT 235 if (!__msan_has_dynamic_component()) { 236 __msan_unpoison(endptr, sizeof(*endptr)); 237 } 238 return res; 239} 240 241INTERCEPTOR(float, strtof, const char *nptr, char **endptr) { // NOLINT 242 ENSURE_MSAN_INITED(); 243 float res = REAL(strtof)(nptr, endptr); // NOLINT 244 if (!__msan_has_dynamic_component()) { 245 __msan_unpoison(endptr, sizeof(*endptr)); 246 } 247 return res; 248} 249 250INTERCEPTOR(long double, strtold, const char *nptr, char **endptr) { // NOLINT 251 ENSURE_MSAN_INITED(); 252 long double res = REAL(strtold)(nptr, endptr); // NOLINT 253 if (!__msan_has_dynamic_component()) { 254 __msan_unpoison(endptr, sizeof(*endptr)); 255 } 256 return res; 257} 258 259INTERCEPTOR(int, vsnprintf, char *str, uptr size, 260 const char *format, va_list ap) { 261 ENSURE_MSAN_INITED(); 262 int res = REAL(vsnprintf)(str, size, format, ap); 263 if (!__msan_has_dynamic_component()) { 264 __msan_unpoison(str, res + 1); 265 } 266 return res; 267} 268 269INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) { 270 ENSURE_MSAN_INITED(); 271 int res = REAL(vsprintf)(str, format, ap); 272 if (!__msan_has_dynamic_component()) { 273 __msan_unpoison(str, res + 1); 274 } 275 return res; 276} 277 278INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) { 279 ENSURE_MSAN_INITED(); 280 int res = REAL(vswprintf)(str, size, format, ap); 281 if (!__msan_has_dynamic_component()) { 282 __msan_unpoison(str, 4 * (res + 1)); 283 } 284 return res; 285} 286 287INTERCEPTOR(int, sprintf, char *str, const char *format, ...) { // NOLINT 288 ENSURE_MSAN_INITED(); 289 va_list ap; 290 va_start(ap, format); 291 int res = vsprintf(str, format, ap); // NOLINT 292 va_end(ap); 293 return res; 294} 295 296INTERCEPTOR(int, snprintf, char *str, uptr size, const char *format, ...) { 297 ENSURE_MSAN_INITED(); 298 va_list ap; 299 va_start(ap, format); 300 int res = vsnprintf(str, size, format, ap); 301 va_end(ap); 302 return res; 303} 304 305INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) { 306 ENSURE_MSAN_INITED(); 307 va_list ap; 308 va_start(ap, format); 309 int res = vswprintf(str, size, format, ap); 310 va_end(ap); 311 return res; 312} 313 314// SIZE_T strftime(char *s, SIZE_T max, const char *format,const struct tm *tm); 315INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format, 316 void *tm) { 317 ENSURE_MSAN_INITED(); 318 SIZE_T res = REAL(strftime)(s, max, format, tm); 319 if (res) __msan_unpoison(s, res + 1); 320 return res; 321} 322 323INTERCEPTOR(SIZE_T, wcstombs, void *dest, void *src, SIZE_T size) { 324 ENSURE_MSAN_INITED(); 325 SIZE_T res = REAL(wcstombs)(dest, src, size); 326 if (res != (SIZE_T)-1) __msan_unpoison(dest, res + 1); 327 return res; 328} 329 330// SIZE_T mbstowcs(wchar_t *dest, const char *src, SIZE_T n); 331INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T n) { 332 ENSURE_MSAN_INITED(); 333 SIZE_T res = REAL(mbstowcs)(dest, src, n); 334 if (res != (SIZE_T)-1) __msan_unpoison(dest, (res + 1) * sizeof(wchar_t)); 335 return res; 336} 337 338INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { 339 ENSURE_MSAN_INITED(); 340 SIZE_T res = REAL(wcslen)(s); 341 CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1)); 342 return res; 343} 344 345// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); 346INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { 347 ENSURE_MSAN_INITED(); 348 wchar_t *res = REAL(wcschr)(s, wc, ps); 349 return res; 350} 351 352// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); 353INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { 354 ENSURE_MSAN_INITED(); 355 wchar_t *res = REAL(wcscpy)(dest, src); 356 __msan_copy_poison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1)); 357 return res; 358} 359 360// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n); 361INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { 362 ENSURE_MSAN_INITED(); 363 wchar_t *res = REAL(wmemcpy)(dest, src, n); 364 __msan_copy_poison(dest, src, n * sizeof(wchar_t)); 365 return res; 366} 367 368INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) { 369 CHECK(MEM_IS_APP(s)); 370 ENSURE_MSAN_INITED(); 371 wchar_t *res = (wchar_t *)fast_memset(s, c, n * sizeof(wchar_t)); 372 __msan_unpoison(s, n * sizeof(wchar_t)); 373 return res; 374} 375 376INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) { 377 ENSURE_MSAN_INITED(); 378 wchar_t *res = REAL(wmemmove)(dest, src, n); 379 __msan_move_poison(dest, src, n * sizeof(wchar_t)); 380 return res; 381} 382 383INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) { 384 ENSURE_MSAN_INITED(); 385 int res = REAL(wcscmp)(s1, s2); 386 return res; 387} 388 389INTERCEPTOR(double, wcstod, const wchar_t *nptr, wchar_t **endptr) { 390 ENSURE_MSAN_INITED(); 391 double res = REAL(wcstod)(nptr, endptr); 392 __msan_unpoison(endptr, sizeof(*endptr)); 393 return res; 394} 395 396// #define UNSUPPORTED(name) \ 397// INTERCEPTOR(void, name, void) { \ 398// Printf("MSAN: Unsupported %s\n", __FUNCTION__); \ 399// Die(); \ 400// } 401 402// FIXME: intercept the following functions: 403// Note, they only matter when running without a dynamic tool. 404// UNSUPPORTED(wcscoll_l) 405// UNSUPPORTED(wcsnrtombs) 406// UNSUPPORTED(wcstol) 407// UNSUPPORTED(wcstoll) 408// UNSUPPORTED(wcstold) 409// UNSUPPORTED(wcstoul) 410// UNSUPPORTED(wcstoull) 411// UNSUPPORTED(wcsxfrm_l) 412// UNSUPPORTED(wcsdup) 413// UNSUPPORTED(wcsftime) 414// UNSUPPORTED(wcsstr) 415// UNSUPPORTED(wcsrchr) 416// UNSUPPORTED(wctob) 417 418INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { 419 ENSURE_MSAN_INITED(); 420 int res = REAL(gettimeofday)(tv, tz); 421 if (tv) 422 __msan_unpoison(tv, 16); 423 if (tz) 424 __msan_unpoison(tz, 8); 425 return res; 426} 427 428INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) { 429 ENSURE_MSAN_INITED(); 430 char *res = REAL(fcvt)(x, a, b, c); 431 if (!__msan_has_dynamic_component()) { 432 __msan_unpoison(b, sizeof(*b)); 433 __msan_unpoison(c, sizeof(*c)); 434 } 435 return res; 436} 437 438INTERCEPTOR(char *, getenv, char *name) { 439 ENSURE_MSAN_INITED(); 440 char *res = REAL(getenv)(name); 441 if (!__msan_has_dynamic_component()) { 442 if (res) 443 __msan_unpoison(res, REAL(strlen)(res) + 1); 444 } 445 return res; 446} 447 448INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { 449 ENSURE_MSAN_INITED(); 450 int res = REAL(__fxstat)(magic, fd, buf); 451 if (!res) 452 __msan_unpoison(buf, __msan::struct_stat_sz); 453 return res; 454} 455 456INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { 457 ENSURE_MSAN_INITED(); 458 int res = REAL(__fxstat64)(magic, fd, buf); 459 if (!res) 460 __msan_unpoison(buf, __msan::struct_stat64_sz); 461 return res; 462} 463 464INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) { 465 ENSURE_MSAN_INITED(); 466 int res = REAL(__xstat)(magic, path, buf); 467 if (!res) 468 __msan_unpoison(buf, __msan::struct_stat_sz); 469 return res; 470} 471 472INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) { 473 ENSURE_MSAN_INITED(); 474 int res = REAL(__xstat64)(magic, path, buf); 475 if (!res) 476 __msan_unpoison(buf, __msan::struct_stat64_sz); 477 return res; 478} 479 480INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) { 481 ENSURE_MSAN_INITED(); 482 int res = REAL(__lxstat)(magic, path, buf); 483 if (!res) 484 __msan_unpoison(buf, __msan::struct_stat_sz); 485 return res; 486} 487 488INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) { 489 ENSURE_MSAN_INITED(); 490 int res = REAL(__lxstat64)(magic, path, buf); 491 if (!res) 492 __msan_unpoison(buf, __msan::struct_stat64_sz); 493 return res; 494} 495 496INTERCEPTOR(int, pipe, int pipefd[2]) { 497 if (msan_init_is_running) 498 return REAL(pipe)(pipefd); 499 ENSURE_MSAN_INITED(); 500 int res = REAL(pipe)(pipefd); 501 if (!res) 502 __msan_unpoison(pipefd, sizeof(int[2])); 503 return res; 504} 505 506INTERCEPTOR(int, wait, int *status) { 507 ENSURE_MSAN_INITED(); 508 int res = REAL(wait)(status); 509 if (status) 510 __msan_unpoison(status, sizeof(*status)); 511 return res; 512} 513 514INTERCEPTOR(int, waitpid, int pid, int *status, int options) { 515 if (msan_init_is_running) 516 return REAL(waitpid)(pid, status, options); 517 ENSURE_MSAN_INITED(); 518 int res = REAL(waitpid)(pid, status, options); 519 if (status) 520 __msan_unpoison(status, sizeof(*status)); 521 return res; 522} 523 524INTERCEPTOR(char *, fgets, char *s, int size, void *stream) { 525 ENSURE_MSAN_INITED(); 526 char *res = REAL(fgets)(s, size, stream); 527 if (res) 528 __msan_unpoison(s, REAL(strlen)(s) + 1); 529 return res; 530} 531 532INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { 533 ENSURE_MSAN_INITED(); 534 char *res = REAL(fgets_unlocked)(s, size, stream); 535 if (res) 536 __msan_unpoison(s, REAL(strlen)(s) + 1); 537 return res; 538} 539 540INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) { 541 ENSURE_MSAN_INITED(); 542 char *res = REAL(getcwd)(buf, size); 543 if (res) 544 __msan_unpoison(buf, REAL(strlen)(buf) + 1); 545 return res; 546} 547 548INTERCEPTOR(char *, realpath, char *path, char *abspath) { 549 ENSURE_MSAN_INITED(); 550 char *res = REAL(realpath)(path, abspath); 551 if (res) 552 __msan_unpoison(abspath, REAL(strlen)(abspath) + 1); 553 return res; 554} 555 556INTERCEPTOR(int, getrlimit, int resource, void *rlim) { 557 if (msan_init_is_running) 558 return REAL(getrlimit)(resource, rlim); 559 ENSURE_MSAN_INITED(); 560 int res = REAL(getrlimit)(resource, rlim); 561 if (!res) 562 __msan_unpoison(rlim, __msan::struct_rlimit_sz); 563 return res; 564} 565 566INTERCEPTOR(int, getrlimit64, int resource, void *rlim) { 567 if (msan_init_is_running) 568 return REAL(getrlimit64)(resource, rlim); 569 ENSURE_MSAN_INITED(); 570 int res = REAL(getrlimit64)(resource, rlim); 571 if (!res) 572 __msan_unpoison(rlim, __msan::struct_rlimit64_sz); 573 return res; 574} 575 576INTERCEPTOR(int, statfs, const char *s, void *buf) { 577 ENSURE_MSAN_INITED(); 578 int res = REAL(statfs)(s, buf); 579 if (!res) 580 __msan_unpoison(buf, __msan::struct_statfs_sz); 581 return res; 582} 583 584INTERCEPTOR(int, fstatfs, int fd, void *buf) { 585 ENSURE_MSAN_INITED(); 586 int res = REAL(fstatfs)(fd, buf); 587 if (!res) 588 __msan_unpoison(buf, __msan::struct_statfs_sz); 589 return res; 590} 591 592INTERCEPTOR(int, statfs64, const char *s, void *buf) { 593 ENSURE_MSAN_INITED(); 594 int res = REAL(statfs64)(s, buf); 595 if (!res) 596 __msan_unpoison(buf, __msan::struct_statfs64_sz); 597 return res; 598} 599 600INTERCEPTOR(int, fstatfs64, int fd, void *buf) { 601 ENSURE_MSAN_INITED(); 602 int res = REAL(fstatfs64)(fd, buf); 603 if (!res) 604 __msan_unpoison(buf, __msan::struct_statfs64_sz); 605 return res; 606} 607 608INTERCEPTOR(int, uname, void *utsname) { 609 ENSURE_MSAN_INITED(); 610 int res = REAL(uname)(utsname); 611 if (!res) { 612 __msan_unpoison(utsname, __msan::struct_utsname_sz); 613 } 614 return res; 615} 616 617INTERCEPTOR(int, gethostname, char *name, SIZE_T len) { 618 ENSURE_MSAN_INITED(); 619 int res = REAL(gethostname)(name, len); 620 if (!res) { 621 SIZE_T real_len = REAL(strnlen)(name, len); 622 if (real_len < len) 623 ++real_len; 624 __msan_unpoison(name, real_len); 625 } 626 return res; 627} 628 629INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents, 630 int timeout) { 631 ENSURE_MSAN_INITED(); 632 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout); 633 if (res > 0) { 634 __msan_unpoison(events, __msan::struct_epoll_event_sz * res); 635 } 636 return res; 637} 638 639INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, 640 int timeout, void *sigmask) { 641 ENSURE_MSAN_INITED(); 642 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask); 643 if (res > 0) { 644 __msan_unpoison(events, __msan::struct_epoll_event_sz * res); 645 } 646 return res; 647} 648 649INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { 650 ENSURE_MSAN_INITED(); 651 SSIZE_T res = REAL(recv)(fd, buf, len, flags); 652 if (res > 0) 653 __msan_unpoison(buf, res); 654 return res; 655} 656 657INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, 658 void *srcaddr, void *addrlen) { 659 ENSURE_MSAN_INITED(); 660 SIZE_T srcaddr_sz; 661 if (srcaddr) 662 srcaddr_sz = __msan_get_socklen_t(addrlen); 663 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); 664 if (res > 0) { 665 __msan_unpoison(buf, res); 666 if (srcaddr) { 667 SIZE_T sz = __msan_get_socklen_t(addrlen); 668 __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz); 669 } 670 } 671 return res; 672} 673 674INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct msghdr *msg, int flags) { 675 ENSURE_MSAN_INITED(); 676 SSIZE_T res = REAL(recvmsg)(fd, msg, flags); 677 if (res > 0) { 678 for (SIZE_T i = 0; i < __msan_get_msghdr_iovlen(msg); ++i) 679 __msan_unpoison(__msan_get_msghdr_iov_iov_base(msg, i), 680 __msan_get_msghdr_iov_iov_len(msg, i)); 681 } 682 return res; 683} 684 685INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { 686 GET_MALLOC_STACK_TRACE; 687 if (!msan_inited) { 688 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 689 const SIZE_T kCallocPoolSize = 1024; 690 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 691 static SIZE_T allocated; 692 SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 693 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 694 allocated += size_in_words; 695 CHECK(allocated < kCallocPoolSize); 696 return mem; 697 } 698 return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true); 699} 700 701INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { 702 GET_MALLOC_STACK_TRACE; 703 return MsanReallocate(&stack, ptr, size, sizeof(u64), false); 704} 705 706INTERCEPTOR(void *, malloc, SIZE_T size) { 707 GET_MALLOC_STACK_TRACE; 708 return MsanReallocate(&stack, 0, size, sizeof(u64), false); 709} 710 711INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, 712 int fd, OFF_T offset) { 713 ENSURE_MSAN_INITED(); 714 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset); 715 if (res != (void*)-1) 716 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 717 return res; 718} 719 720INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, 721 int fd, OFF64_T offset) { 722 ENSURE_MSAN_INITED(); 723 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset); 724 if (res != (void*)-1) 725 __msan_unpoison(res, RoundUpTo(length, GetPageSize())); 726 return res; 727} 728 729struct dlinfo { 730 char *dli_fname; 731 void *dli_fbase; 732 char *dli_sname; 733 void *dli_saddr; 734}; 735 736INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { 737 ENSURE_MSAN_INITED(); 738 int res = REAL(dladdr)(addr, info); 739 if (res != 0) { 740 __msan_unpoison(info, sizeof(*info)); 741 if (info->dli_fname) 742 __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); 743 if (info->dli_sname) 744 __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); 745 } 746 return res; 747} 748 749INTERCEPTOR(int, getrusage, int who, void *usage) { 750 ENSURE_MSAN_INITED(); 751 int res = REAL(getrusage)(who, usage); 752 if (res == 0) { 753 __msan_unpoison(usage, __msan::struct_rusage_sz); 754 } 755 return res; 756} 757 758#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 759 __msan_unpoison(ptr, size) 760#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) do { } while (false) 761#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 762 do { \ 763 ctx = 0; \ 764 (void)ctx; \ 765 ENSURE_MSAN_INITED(); \ 766 } while (false) 767#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false) 768#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false) 769#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ 770 do { } while (false) // FIXME 771#include "sanitizer_common/sanitizer_common_interceptors.inc" 772 773// static 774void *fast_memset(void *ptr, int c, SIZE_T n) { 775 // hack until we have a really fast internal_memset 776 if (sizeof(uptr) == 8 && 777 (n % 8) == 0 && 778 ((uptr)ptr % 8) == 0 && 779 (c == 0 || c == -1)) { 780 // Printf("memset %p %zd %x\n", ptr, n, c); 781 uptr to_store = c ? -1L : 0L; 782 uptr *p = (uptr*)ptr; 783 for (SIZE_T i = 0; i < n / 8; i++) 784 p[i] = to_store; 785 return ptr; 786 } 787 return internal_memset(ptr, c, n); 788} 789 790// static 791void *fast_memcpy(void *dst, const void *src, SIZE_T n) { 792 // Same hack as in fast_memset above. 793 if (sizeof(uptr) == 8 && 794 (n % 8) == 0 && 795 ((uptr)dst % 8) == 0 && 796 ((uptr)src % 8) == 0) { 797 uptr *d = (uptr*)dst; 798 uptr *s = (uptr*)src; 799 for (SIZE_T i = 0; i < n / 8; i++) 800 d[i] = s[i]; 801 return dst; 802 } 803 return internal_memcpy(dst, src, n); 804} 805 806// These interface functions reside here so that they can use 807// fast_memset, etc. 808void __msan_unpoison(void *a, uptr size) { 809 if (!MEM_IS_APP(a)) return; 810 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size); 811} 812 813void __msan_poison(void *a, uptr size) { 814 if (!MEM_IS_APP(a)) return; 815 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 816 __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size); 817} 818 819void __msan_poison_stack(void *a, uptr size) { 820 if (!MEM_IS_APP(a)) return; 821 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 822 __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size); 823} 824 825void __msan_clear_and_unpoison(void *a, uptr size) { 826 fast_memset(a, 0, size); 827 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size); 828} 829 830void __msan_copy_origin(void *dst, const void *src, uptr size) { 831 if (!__msan_get_track_origins()) return; 832 if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return; 833 uptr d = MEM_TO_ORIGIN(dst); 834 uptr s = MEM_TO_ORIGIN(src); 835 uptr beg = d & ~3UL; // align down. 836 uptr end = (d + size + 3) & ~3UL; // align up. 837 s = s & ~3UL; // align down. 838 fast_memcpy((void*)beg, (void*)s, end - beg); 839} 840 841void __msan_copy_poison(void *dst, const void *src, uptr size) { 842 if (!MEM_IS_APP(dst)) return; 843 if (!MEM_IS_APP(src)) return; 844 fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst), 845 (void*)MEM_TO_SHADOW((uptr)src), size); 846 __msan_copy_origin(dst, src, size); 847} 848 849void __msan_move_poison(void *dst, const void *src, uptr size) { 850 if (!MEM_IS_APP(dst)) return; 851 if (!MEM_IS_APP(src)) return; 852 internal_memmove((void*)MEM_TO_SHADOW((uptr)dst), 853 (void*)MEM_TO_SHADOW((uptr)src), size); 854 __msan_copy_origin(dst, src, size); 855} 856 857void *__msan_memcpy(void *dest, const void *src, SIZE_T n) { 858 ENSURE_MSAN_INITED(); 859 void *res = fast_memcpy(dest, src, n); 860 __msan_copy_poison(dest, src, n); 861 return res; 862} 863 864void *__msan_memset(void *s, int c, SIZE_T n) { 865 ENSURE_MSAN_INITED(); 866 void *res = fast_memset(s, c, n); 867 __msan_unpoison(s, n); 868 return res; 869} 870 871void *__msan_memmove(void *dest, const void *src, SIZE_T n) { 872 ENSURE_MSAN_INITED(); 873 void *res = REAL(memmove)(dest, src, n); 874 __msan_move_poison(dest, src, n); 875 return res; 876} 877 878namespace __msan { 879void InitializeInterceptors() { 880 static int inited = 0; 881 CHECK_EQ(inited, 0); 882 SANITIZER_COMMON_INTERCEPTORS_INIT; 883 884 INTERCEPT_FUNCTION(mmap); 885 INTERCEPT_FUNCTION(mmap64); 886 INTERCEPT_FUNCTION(posix_memalign); 887 INTERCEPT_FUNCTION(malloc); 888 INTERCEPT_FUNCTION(calloc); 889 INTERCEPT_FUNCTION(realloc); 890 INTERCEPT_FUNCTION(free); 891 INTERCEPT_FUNCTION(fread); 892 INTERCEPT_FUNCTION(fread_unlocked); 893 INTERCEPT_FUNCTION(readlink); 894 INTERCEPT_FUNCTION(readdir); 895 INTERCEPT_FUNCTION(memcpy); 896 INTERCEPT_FUNCTION(memset); 897 INTERCEPT_FUNCTION(memmove); 898 INTERCEPT_FUNCTION(wmemset); 899 INTERCEPT_FUNCTION(wmemcpy); 900 INTERCEPT_FUNCTION(wmemmove); 901 INTERCEPT_FUNCTION(strcpy); // NOLINT 902 INTERCEPT_FUNCTION(strdup); 903 INTERCEPT_FUNCTION(strncpy); // NOLINT 904 INTERCEPT_FUNCTION(strlen); 905 INTERCEPT_FUNCTION(strnlen); 906 INTERCEPT_FUNCTION(gcvt); 907 INTERCEPT_FUNCTION(strcat); // NOLINT 908 INTERCEPT_FUNCTION(strncat); // NOLINT 909 INTERCEPT_FUNCTION(strtol); 910 INTERCEPT_FUNCTION(strtoll); 911 INTERCEPT_FUNCTION(strtoul); 912 INTERCEPT_FUNCTION(strtoull); 913 INTERCEPT_FUNCTION(strtod); 914 INTERCEPT_FUNCTION(strtof); 915 INTERCEPT_FUNCTION(strtold); 916 INTERCEPT_FUNCTION(vsprintf); 917 INTERCEPT_FUNCTION(vsnprintf); 918 INTERCEPT_FUNCTION(vswprintf); 919 INTERCEPT_FUNCTION(sprintf); // NOLINT 920 INTERCEPT_FUNCTION(snprintf); 921 INTERCEPT_FUNCTION(swprintf); 922 INTERCEPT_FUNCTION(strftime); 923 INTERCEPT_FUNCTION(wcstombs); 924 INTERCEPT_FUNCTION(mbstowcs); 925 INTERCEPT_FUNCTION(wcslen); 926 INTERCEPT_FUNCTION(wcschr); 927 INTERCEPT_FUNCTION(wcscpy); 928 INTERCEPT_FUNCTION(wcscmp); 929 INTERCEPT_FUNCTION(wcstod); 930 INTERCEPT_FUNCTION(getenv); 931 INTERCEPT_FUNCTION(gettimeofday); 932 INTERCEPT_FUNCTION(fcvt); 933 INTERCEPT_FUNCTION(__fxstat); 934 INTERCEPT_FUNCTION(__xstat); 935 INTERCEPT_FUNCTION(__lxstat); 936 INTERCEPT_FUNCTION(__fxstat64); 937 INTERCEPT_FUNCTION(__xstat64); 938 INTERCEPT_FUNCTION(__lxstat64); 939 INTERCEPT_FUNCTION(pipe); 940 INTERCEPT_FUNCTION(wait); 941 INTERCEPT_FUNCTION(waitpid); 942 INTERCEPT_FUNCTION(fgets); 943 INTERCEPT_FUNCTION(fgets_unlocked); 944 INTERCEPT_FUNCTION(getcwd); 945 INTERCEPT_FUNCTION(realpath); 946 INTERCEPT_FUNCTION(getrlimit); 947 INTERCEPT_FUNCTION(getrlimit64); 948 INTERCEPT_FUNCTION(statfs); 949 INTERCEPT_FUNCTION(fstatfs); 950 INTERCEPT_FUNCTION(statfs64); 951 INTERCEPT_FUNCTION(fstatfs64); 952 INTERCEPT_FUNCTION(uname); 953 INTERCEPT_FUNCTION(gethostname); 954 INTERCEPT_FUNCTION(epoll_wait); 955 INTERCEPT_FUNCTION(epoll_pwait); 956 INTERCEPT_FUNCTION(recv); 957 INTERCEPT_FUNCTION(recvfrom); 958 INTERCEPT_FUNCTION(recvmsg); 959 INTERCEPT_FUNCTION(dladdr); 960 INTERCEPT_FUNCTION(getrusage); 961 inited = 1; 962} 963} // namespace __msan 964