1 //===-- sanitizer_mac.cc --------------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file is shared between various sanitizers' runtime libraries and 9 // implements OSX-specific functions. 10 //===----------------------------------------------------------------------===// 11 12 #include "sanitizer_platform.h" 13 #if SANITIZER_MAC 14 #include "sanitizer_mac.h" 15 16 // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so 17 // the clients will most certainly use 64-bit ones as well. 18 #ifndef _DARWIN_USE_64_BIT_INODE 19 #define _DARWIN_USE_64_BIT_INODE 1 20 #endif 21 #include <stdio.h> 22 23 #include "sanitizer_common.h" 24 #include "sanitizer_file.h" 25 #include "sanitizer_flags.h" 26 #include "sanitizer_internal_defs.h" 27 #include "sanitizer_libc.h" 28 #include "sanitizer_placement_new.h" 29 #include "sanitizer_platform_limits_posix.h" 30 #include "sanitizer_procmaps.h" 31 32 #if !SANITIZER_IOS 33 #include <crt_externs.h> // for _NSGetEnviron 34 #else 35 extern char **environ; 36 #endif 37 38 #if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__) 39 #define SANITIZER_OS_TRACE 1 40 #include <os/trace.h> 41 #else 42 #define SANITIZER_OS_TRACE 0 43 #endif 44 45 #if !SANITIZER_IOS 46 #include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron 47 #else 48 extern "C" { 49 extern char ***_NSGetArgv(void); 50 } 51 #endif 52 53 #include <asl.h> 54 #include <dlfcn.h> // for dladdr() 55 #include <errno.h> 56 #include <fcntl.h> 57 #include <libkern/OSAtomic.h> 58 #include <mach-o/dyld.h> 59 #include <mach/mach.h> 60 #include <mach/vm_statistics.h> 61 #include <pthread.h> 62 #include <sched.h> 63 #include <signal.h> 64 #include <stdlib.h> 65 #include <sys/mman.h> 66 #include <sys/resource.h> 67 #include <sys/stat.h> 68 #include <sys/sysctl.h> 69 #include <sys/types.h> 70 #include <sys/wait.h> 71 #include <unistd.h> 72 #include <util.h> 73 74 // From <crt_externs.h>, but we don't have that file on iOS. 75 extern "C" { 76 extern char ***_NSGetArgv(void); 77 extern char ***_NSGetEnviron(void); 78 } 79 80 // From <mach/mach_vm.h>, but we don't have that file on iOS. 81 extern "C" { 82 extern kern_return_t mach_vm_region_recurse( 83 vm_map_t target_task, 84 mach_vm_address_t *address, 85 mach_vm_size_t *size, 86 natural_t *nesting_depth, 87 vm_region_recurse_info_t info, 88 mach_msg_type_number_t *infoCnt); 89 } 90 91 namespace __sanitizer { 92 93 #include "sanitizer_syscall_generic.inc" 94 95 // Direct syscalls, don't call libmalloc hooks (but not available on 10.6). 96 extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes, 97 off_t off) SANITIZER_WEAK_ATTRIBUTE; 98 extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE; 99 100 // ---------------------- sanitizer_libc.h 101 uptr internal_mmap(void *addr, size_t length, int prot, int flags, 102 int fd, u64 offset) { 103 if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL); 104 if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset); 105 return (uptr)mmap(addr, length, prot, flags, fd, offset); 106 } 107 108 uptr internal_munmap(void *addr, uptr length) { 109 if (&__munmap) return __munmap(addr, length); 110 return munmap(addr, length); 111 } 112 113 int internal_mprotect(void *addr, uptr length, int prot) { 114 return mprotect(addr, length, prot); 115 } 116 117 uptr internal_close(fd_t fd) { 118 return close(fd); 119 } 120 121 uptr internal_open(const char *filename, int flags) { 122 return open(filename, flags); 123 } 124 125 uptr internal_open(const char *filename, int flags, u32 mode) { 126 return open(filename, flags, mode); 127 } 128 129 uptr internal_read(fd_t fd, void *buf, uptr count) { 130 return read(fd, buf, count); 131 } 132 133 uptr internal_write(fd_t fd, const void *buf, uptr count) { 134 return write(fd, buf, count); 135 } 136 137 uptr internal_stat(const char *path, void *buf) { 138 return stat(path, (struct stat *)buf); 139 } 140 141 uptr internal_lstat(const char *path, void *buf) { 142 return lstat(path, (struct stat *)buf); 143 } 144 145 uptr internal_fstat(fd_t fd, void *buf) { 146 return fstat(fd, (struct stat *)buf); 147 } 148 149 uptr internal_filesize(fd_t fd) { 150 struct stat st; 151 if (internal_fstat(fd, &st)) 152 return -1; 153 return (uptr)st.st_size; 154 } 155 156 uptr internal_dup2(int oldfd, int newfd) { 157 return dup2(oldfd, newfd); 158 } 159 160 uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 161 return readlink(path, buf, bufsize); 162 } 163 164 uptr internal_unlink(const char *path) { 165 return unlink(path); 166 } 167 168 uptr internal_sched_yield() { 169 return sched_yield(); 170 } 171 172 void internal__exit(int exitcode) { 173 _exit(exitcode); 174 } 175 176 unsigned int internal_sleep(unsigned int seconds) { 177 return sleep(seconds); 178 } 179 180 uptr internal_getpid() { 181 return getpid(); 182 } 183 184 int internal_sigaction(int signum, const void *act, void *oldact) { 185 return sigaction(signum, 186 (struct sigaction *)act, (struct sigaction *)oldact); 187 } 188 189 void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); } 190 191 uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 192 __sanitizer_sigset_t *oldset) { 193 // Don't use sigprocmask here, because it affects all threads. 194 return pthread_sigmask(how, set, oldset); 195 } 196 197 // Doesn't call pthread_atfork() handlers (but not available on 10.6). 198 extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE; 199 200 int internal_fork() { 201 if (&__fork) 202 return __fork(); 203 return fork(); 204 } 205 206 int internal_forkpty(int *amaster) { 207 int master, slave; 208 if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; 209 int pid = internal_fork(); 210 if (pid == -1) { 211 close(master); 212 close(slave); 213 return -1; 214 } 215 if (pid == 0) { 216 close(master); 217 if (login_tty(slave) != 0) { 218 // We already forked, there's not much we can do. Let's quit. 219 Report("login_tty failed (errno %d)\n", errno); 220 internal__exit(1); 221 } 222 } else { 223 *amaster = master; 224 close(slave); 225 } 226 return pid; 227 } 228 229 uptr internal_rename(const char *oldpath, const char *newpath) { 230 return rename(oldpath, newpath); 231 } 232 233 uptr internal_ftruncate(fd_t fd, uptr size) { 234 return ftruncate(fd, size); 235 } 236 237 uptr internal_execve(const char *filename, char *const argv[], 238 char *const envp[]) { 239 return execve(filename, argv, envp); 240 } 241 242 uptr internal_waitpid(int pid, int *status, int options) { 243 return waitpid(pid, status, options); 244 } 245 246 // ----------------- sanitizer_common.h 247 bool FileExists(const char *filename) { 248 struct stat st; 249 if (stat(filename, &st)) 250 return false; 251 // Sanity check: filename is a regular file. 252 return S_ISREG(st.st_mode); 253 } 254 255 tid_t GetTid() { 256 tid_t tid; 257 pthread_threadid_np(nullptr, &tid); 258 return tid; 259 } 260 261 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 262 uptr *stack_bottom) { 263 CHECK(stack_top); 264 CHECK(stack_bottom); 265 uptr stacksize = pthread_get_stacksize_np(pthread_self()); 266 // pthread_get_stacksize_np() returns an incorrect stack size for the main 267 // thread on Mavericks. See 268 // https://github.com/google/sanitizers/issues/261 269 if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization && 270 stacksize == (1 << 19)) { 271 struct rlimit rl; 272 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 273 // Most often rl.rlim_cur will be the desired 8M. 274 if (rl.rlim_cur < kMaxThreadStackSize) { 275 stacksize = rl.rlim_cur; 276 } else { 277 stacksize = kMaxThreadStackSize; 278 } 279 } 280 void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 281 *stack_top = (uptr)stackaddr; 282 *stack_bottom = *stack_top - stacksize; 283 } 284 285 char **GetEnviron() { 286 #if !SANITIZER_IOS 287 char ***env_ptr = _NSGetEnviron(); 288 if (!env_ptr) { 289 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is " 290 "called after libSystem_initializer().\n"); 291 CHECK(env_ptr); 292 } 293 char **environ = *env_ptr; 294 #endif 295 CHECK(environ); 296 return environ; 297 } 298 299 const char *GetEnv(const char *name) { 300 char **env = GetEnviron(); 301 uptr name_len = internal_strlen(name); 302 while (*env != 0) { 303 uptr len = internal_strlen(*env); 304 if (len > name_len) { 305 const char *p = *env; 306 if (!internal_memcmp(p, name, name_len) && 307 p[name_len] == '=') { // Match. 308 return *env + name_len + 1; // String starting after =. 309 } 310 } 311 env++; 312 } 313 return 0; 314 } 315 316 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 317 CHECK_LE(kMaxPathLength, buf_len); 318 319 // On OS X the executable path is saved to the stack by dyld. Reading it 320 // from there is much faster than calling dladdr, especially for large 321 // binaries with symbols. 322 InternalScopedString exe_path(kMaxPathLength); 323 uint32_t size = exe_path.size(); 324 if (_NSGetExecutablePath(exe_path.data(), &size) == 0 && 325 realpath(exe_path.data(), buf) != 0) { 326 return internal_strlen(buf); 327 } 328 return 0; 329 } 330 331 uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) { 332 return ReadBinaryName(buf, buf_len); 333 } 334 335 void ReExec() { 336 UNIMPLEMENTED(); 337 } 338 339 uptr GetPageSize() { 340 return sysconf(_SC_PAGESIZE); 341 } 342 343 BlockingMutex::BlockingMutex() { 344 internal_memset(this, 0, sizeof(*this)); 345 } 346 347 void BlockingMutex::Lock() { 348 CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 349 CHECK_EQ(OS_SPINLOCK_INIT, 0); 350 CHECK_EQ(owner_, 0); 351 OSSpinLockLock((OSSpinLock*)&opaque_storage_); 352 } 353 354 void BlockingMutex::Unlock() { 355 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 356 } 357 358 void BlockingMutex::CheckLocked() { 359 CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0); 360 } 361 362 u64 NanoTime() { 363 return 0; 364 } 365 366 uptr GetTlsSize() { 367 return 0; 368 } 369 370 void InitTlsSize() { 371 } 372 373 uptr TlsBaseAddr() { 374 uptr segbase = 0; 375 #if defined(__x86_64__) 376 asm("movq %%gs:0,%0" : "=r"(segbase)); 377 #elif defined(__i386__) 378 asm("movl %%gs:0,%0" : "=r"(segbase)); 379 #endif 380 return segbase; 381 } 382 383 // The size of the tls on darwin does not appear to be well documented, 384 // however the vm memory map suggests that it is 1024 uptrs in size, 385 // with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386. 386 uptr TlsSize() { 387 #if defined(__x86_64__) || defined(__i386__) 388 return 1024 * sizeof(uptr); 389 #else 390 return 0; 391 #endif 392 } 393 394 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 395 uptr *tls_addr, uptr *tls_size) { 396 #if !SANITIZER_GO 397 uptr stack_top, stack_bottom; 398 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 399 *stk_addr = stack_bottom; 400 *stk_size = stack_top - stack_bottom; 401 *tls_addr = TlsBaseAddr(); 402 *tls_size = TlsSize(); 403 #else 404 *stk_addr = 0; 405 *stk_size = 0; 406 *tls_addr = 0; 407 *tls_size = 0; 408 #endif 409 } 410 411 void ListOfModules::init() { 412 clearOrInit(); 413 MemoryMappingLayout memory_mapping(false); 414 memory_mapping.DumpListOfModules(&modules_); 415 } 416 417 void ListOfModules::fallbackInit() { clear(); } 418 419 static HandleSignalMode GetHandleSignalModeImpl(int signum) { 420 switch (signum) { 421 case SIGABRT: 422 return common_flags()->handle_abort; 423 case SIGILL: 424 return common_flags()->handle_sigill; 425 case SIGFPE: 426 return common_flags()->handle_sigfpe; 427 case SIGSEGV: 428 return common_flags()->handle_segv; 429 case SIGBUS: 430 return common_flags()->handle_sigbus; 431 } 432 return kHandleSignalNo; 433 } 434 435 HandleSignalMode GetHandleSignalMode(int signum) { 436 // Handling fatal signals on watchOS and tvOS devices is disallowed. 437 if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) 438 return kHandleSignalNo; 439 HandleSignalMode result = GetHandleSignalModeImpl(signum); 440 if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) 441 return kHandleSignalExclusive; 442 return result; 443 } 444 445 MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; 446 447 MacosVersion GetMacosVersionInternal() { 448 int mib[2] = { CTL_KERN, KERN_OSRELEASE }; 449 char version[100]; 450 uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); 451 for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; 452 // Get the version length. 453 CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1); 454 CHECK_LT(len, maxlen); 455 CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1); 456 switch (version[0]) { 457 case '9': return MACOS_VERSION_LEOPARD; 458 case '1': { 459 switch (version[1]) { 460 case '0': return MACOS_VERSION_SNOW_LEOPARD; 461 case '1': return MACOS_VERSION_LION; 462 case '2': return MACOS_VERSION_MOUNTAIN_LION; 463 case '3': return MACOS_VERSION_MAVERICKS; 464 case '4': return MACOS_VERSION_YOSEMITE; 465 default: 466 if (IsDigit(version[1])) 467 return MACOS_VERSION_UNKNOWN_NEWER; 468 else 469 return MACOS_VERSION_UNKNOWN; 470 } 471 } 472 default: return MACOS_VERSION_UNKNOWN; 473 } 474 } 475 476 MacosVersion GetMacosVersion() { 477 atomic_uint32_t *cache = 478 reinterpret_cast<atomic_uint32_t*>(&cached_macos_version); 479 MacosVersion result = 480 static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire)); 481 if (result == MACOS_VERSION_UNINITIALIZED) { 482 result = GetMacosVersionInternal(); 483 atomic_store(cache, result, memory_order_release); 484 } 485 return result; 486 } 487 488 bool PlatformHasDifferentMemcpyAndMemmove() { 489 // On OS X 10.7 memcpy() and memmove() are both resolved 490 // into memmove$VARIANT$sse42. 491 // See also https://github.com/google/sanitizers/issues/34. 492 // TODO(glider): need to check dynamically that memcpy() and memmove() are 493 // actually the same function. 494 return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; 495 } 496 497 uptr GetRSS() { 498 struct task_basic_info info; 499 unsigned count = TASK_BASIC_INFO_COUNT; 500 kern_return_t result = 501 task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count); 502 if (UNLIKELY(result != KERN_SUCCESS)) { 503 Report("Cannot get task info. Error: %d\n", result); 504 Die(); 505 } 506 return info.resident_size; 507 } 508 509 void *internal_start_thread(void(*func)(void *arg), void *arg) { 510 // Start the thread with signals blocked, otherwise it can steal user signals. 511 __sanitizer_sigset_t set, old; 512 internal_sigfillset(&set); 513 internal_sigprocmask(SIG_SETMASK, &set, &old); 514 pthread_t th; 515 pthread_create(&th, 0, (void*(*)(void *arg))func, arg); 516 internal_sigprocmask(SIG_SETMASK, &old, 0); 517 return th; 518 } 519 520 void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); } 521 522 #if !SANITIZER_GO 523 static BlockingMutex syslog_lock(LINKER_INITIALIZED); 524 #endif 525 526 void WriteOneLineToSyslog(const char *s) { 527 #if !SANITIZER_GO 528 syslog_lock.CheckLocked(); 529 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); 530 #endif 531 } 532 533 void LogMessageOnPrintf(const char *str) { 534 // Log all printf output to CrashLog. 535 if (common_flags()->abort_on_error) 536 CRAppendCrashLogMessage(str); 537 } 538 539 void LogFullErrorReport(const char *buffer) { 540 #if !SANITIZER_GO 541 // Log with os_trace. This will make it into the crash log. 542 #if SANITIZER_OS_TRACE 543 if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { 544 // os_trace requires the message (format parameter) to be a string literal. 545 if (internal_strncmp(SanitizerToolName, "AddressSanitizer", 546 sizeof("AddressSanitizer") - 1) == 0) 547 os_trace("Address Sanitizer reported a failure."); 548 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", 549 sizeof("UndefinedBehaviorSanitizer") - 1) == 0) 550 os_trace("Undefined Behavior Sanitizer reported a failure."); 551 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", 552 sizeof("ThreadSanitizer") - 1) == 0) 553 os_trace("Thread Sanitizer reported a failure."); 554 else 555 os_trace("Sanitizer tool reported a failure."); 556 557 if (common_flags()->log_to_syslog) 558 os_trace("Consult syslog for more information."); 559 } 560 #endif 561 562 // Log to syslog. 563 // The logging on OS X may call pthread_create so we need the threading 564 // environment to be fully initialized. Also, this should never be called when 565 // holding the thread registry lock since that may result in a deadlock. If 566 // the reporting thread holds the thread registry mutex, and asl_log waits 567 // for GCD to dispatch a new thread, the process will deadlock, because the 568 // pthread_create wrapper needs to acquire the lock as well. 569 BlockingMutexLock l(&syslog_lock); 570 if (common_flags()->log_to_syslog) 571 WriteToSyslog(buffer); 572 573 // The report is added to CrashLog as part of logging all of Printf output. 574 #endif 575 } 576 577 SignalContext::WriteFlag SignalContext::GetWriteFlag() const { 578 #if defined(__x86_64__) || defined(__i386__) 579 ucontext_t *ucontext = static_cast<ucontext_t*>(context); 580 return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ; 581 #else 582 return UNKNOWN; 583 #endif 584 } 585 586 static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 587 ucontext_t *ucontext = (ucontext_t*)context; 588 # if defined(__aarch64__) 589 *pc = ucontext->uc_mcontext->__ss.__pc; 590 # if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 591 *bp = ucontext->uc_mcontext->__ss.__fp; 592 # else 593 *bp = ucontext->uc_mcontext->__ss.__lr; 594 # endif 595 *sp = ucontext->uc_mcontext->__ss.__sp; 596 # elif defined(__x86_64__) 597 *pc = ucontext->uc_mcontext->__ss.__rip; 598 *bp = ucontext->uc_mcontext->__ss.__rbp; 599 *sp = ucontext->uc_mcontext->__ss.__rsp; 600 # elif defined(__arm__) 601 *pc = ucontext->uc_mcontext->__ss.__pc; 602 *bp = ucontext->uc_mcontext->__ss.__r[7]; 603 *sp = ucontext->uc_mcontext->__ss.__sp; 604 # elif defined(__i386__) 605 *pc = ucontext->uc_mcontext->__ss.__eip; 606 *bp = ucontext->uc_mcontext->__ss.__ebp; 607 *sp = ucontext->uc_mcontext->__ss.__esp; 608 # else 609 # error "Unknown architecture" 610 # endif 611 } 612 613 void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } 614 615 #if !SANITIZER_GO 616 static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 617 LowLevelAllocator allocator_for_env; 618 619 // Change the value of the env var |name|, leaking the original value. 620 // If |name_value| is NULL, the variable is deleted from the environment, 621 // otherwise the corresponding "NAME=value" string is replaced with 622 // |name_value|. 623 void LeakyResetEnv(const char *name, const char *name_value) { 624 char **env = GetEnviron(); 625 uptr name_len = internal_strlen(name); 626 while (*env != 0) { 627 uptr len = internal_strlen(*env); 628 if (len > name_len) { 629 const char *p = *env; 630 if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { 631 // Match. 632 if (name_value) { 633 // Replace the old value with the new one. 634 *env = const_cast<char*>(name_value); 635 } else { 636 // Shift the subsequent pointers back. 637 char **del = env; 638 do { 639 del[0] = del[1]; 640 } while (*del++); 641 } 642 } 643 } 644 env++; 645 } 646 } 647 648 SANITIZER_WEAK_CXX_DEFAULT_IMPL 649 bool ReexecDisabled() { 650 return false; 651 } 652 653 extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber; 654 static const double kMinDyldVersionWithAutoInterposition = 360.0; 655 656 bool DyldNeedsEnvVariable() { 657 // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users 658 // still may want use them on older systems. On older Darwin platforms, dyld 659 // doesn't export dyldVersionNumber symbol and we simply return true. 660 if (!&dyldVersionNumber) return true; 661 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if 662 // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via 663 // GetMacosVersion() doesn't work for the simulator. Let's instead check 664 // `dyldVersionNumber`, which is exported by dyld, against a known version 665 // number from the first OS release where this appeared. 666 return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; 667 } 668 669 void MaybeReexec() { 670 if (ReexecDisabled()) return; 671 672 // Make sure the dynamic runtime library is preloaded so that the 673 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec 674 // ourselves. 675 Dl_info info; 676 RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info)); 677 char *dyld_insert_libraries = 678 const_cast<char*>(GetEnv(kDyldInsertLibraries)); 679 uptr old_env_len = dyld_insert_libraries ? 680 internal_strlen(dyld_insert_libraries) : 0; 681 uptr fname_len = internal_strlen(info.dli_fname); 682 const char *dylib_name = StripModuleName(info.dli_fname); 683 uptr dylib_name_len = internal_strlen(dylib_name); 684 685 bool lib_is_in_env = dyld_insert_libraries && 686 internal_strstr(dyld_insert_libraries, dylib_name); 687 if (DyldNeedsEnvVariable() && !lib_is_in_env) { 688 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime 689 // library. 690 InternalScopedString program_name(1024); 691 uint32_t buf_size = program_name.size(); 692 _NSGetExecutablePath(program_name.data(), &buf_size); 693 char *new_env = const_cast<char*>(info.dli_fname); 694 if (dyld_insert_libraries) { 695 // Append the runtime dylib name to the existing value of 696 // DYLD_INSERT_LIBRARIES. 697 new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); 698 internal_strncpy(new_env, dyld_insert_libraries, old_env_len); 699 new_env[old_env_len] = ':'; 700 // Copy fname_len and add a trailing zero. 701 internal_strncpy(new_env + old_env_len + 1, info.dli_fname, 702 fname_len + 1); 703 // Ok to use setenv() since the wrappers don't depend on the value of 704 // asan_inited. 705 setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); 706 } else { 707 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. 708 setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); 709 } 710 VReport(1, "exec()-ing the program with\n"); 711 VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); 712 VReport(1, "to enable wrappers.\n"); 713 execv(program_name.data(), *_NSGetArgv()); 714 715 // We get here only if execv() failed. 716 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " 717 "which is required for the sanitizer to work. We tried to set the " 718 "environment variable and re-execute itself, but execv() failed, " 719 "possibly because of sandbox restrictions. Make sure to launch the " 720 "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); 721 RAW_CHECK("execv failed" && 0); 722 } 723 724 // Verify that interceptors really work. We'll use dlsym to locate 725 // "pthread_create", if interceptors are working, it should really point to 726 // "wrap_pthread_create" within our own dylib. 727 Dl_info info_pthread_create; 728 void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create"); 729 RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create)); 730 if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) { 731 Report( 732 "ERROR: Interceptors are not working. This may be because %s is " 733 "loaded too late (e.g. via dlopen). Please launch the executable " 734 "with:\n%s=%s\n", 735 SanitizerToolName, kDyldInsertLibraries, info.dli_fname); 736 RAW_CHECK("interceptors not installed" && 0); 737 } 738 739 if (!lib_is_in_env) 740 return; 741 742 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove 743 // the dylib from the environment variable, because interceptors are installed 744 // and we don't want our children to inherit the variable. 745 746 uptr env_name_len = internal_strlen(kDyldInsertLibraries); 747 // Allocate memory to hold the previous env var name, its value, the '=' 748 // sign and the '\0' char. 749 char *new_env = (char*)allocator_for_env.Allocate( 750 old_env_len + 2 + env_name_len); 751 RAW_CHECK(new_env); 752 internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); 753 internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); 754 new_env[env_name_len] = '='; 755 char *new_env_pos = new_env + env_name_len + 1; 756 757 // Iterate over colon-separated pieces of |dyld_insert_libraries|. 758 char *piece_start = dyld_insert_libraries; 759 char *piece_end = NULL; 760 char *old_env_end = dyld_insert_libraries + old_env_len; 761 do { 762 if (piece_start[0] == ':') piece_start++; 763 piece_end = internal_strchr(piece_start, ':'); 764 if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; 765 if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; 766 uptr piece_len = piece_end - piece_start; 767 768 char *filename_start = 769 (char *)internal_memrchr(piece_start, '/', piece_len); 770 uptr filename_len = piece_len; 771 if (filename_start) { 772 filename_start += 1; 773 filename_len = piece_len - (filename_start - piece_start); 774 } else { 775 filename_start = piece_start; 776 } 777 778 // If the current piece isn't the runtime library name, 779 // append it to new_env. 780 if ((dylib_name_len != filename_len) || 781 (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { 782 if (new_env_pos != new_env + env_name_len + 1) { 783 new_env_pos[0] = ':'; 784 new_env_pos++; 785 } 786 internal_strncpy(new_env_pos, piece_start, piece_len); 787 new_env_pos += piece_len; 788 } 789 // Move on to the next piece. 790 piece_start = piece_end; 791 } while (piece_start < old_env_end); 792 793 // Can't use setenv() here, because it requires the allocator to be 794 // initialized. 795 // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in 796 // a separate function called after InitializeAllocator(). 797 if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; 798 LeakyResetEnv(kDyldInsertLibraries, new_env); 799 } 800 #endif // SANITIZER_GO 801 802 char **GetArgv() { 803 return *_NSGetArgv(); 804 } 805 806 #if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM 807 // The task_vm_info struct is normally provided by the macOS SDK, but we need 808 // fields only available in 10.12+. Declare the struct manually to be able to 809 // build against older SDKs. 810 struct __sanitizer_task_vm_info { 811 mach_vm_size_t virtual_size; 812 integer_t region_count; 813 integer_t page_size; 814 mach_vm_size_t resident_size; 815 mach_vm_size_t resident_size_peak; 816 mach_vm_size_t device; 817 mach_vm_size_t device_peak; 818 mach_vm_size_t internal; 819 mach_vm_size_t internal_peak; 820 mach_vm_size_t external; 821 mach_vm_size_t external_peak; 822 mach_vm_size_t reusable; 823 mach_vm_size_t reusable_peak; 824 mach_vm_size_t purgeable_volatile_pmap; 825 mach_vm_size_t purgeable_volatile_resident; 826 mach_vm_size_t purgeable_volatile_virtual; 827 mach_vm_size_t compressed; 828 mach_vm_size_t compressed_peak; 829 mach_vm_size_t compressed_lifetime; 830 mach_vm_size_t phys_footprint; 831 mach_vm_address_t min_address; 832 mach_vm_address_t max_address; 833 }; 834 #define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \ 835 (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t))) 836 837 uptr GetTaskInfoMaxAddress() { 838 __sanitizer_task_vm_info vm_info = {}; 839 mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT; 840 int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count); 841 if (err == 0) { 842 return vm_info.max_address - 1; 843 } else { 844 // xnu cannot provide vm address limit 845 return 0x200000000 - 1; 846 } 847 } 848 #endif 849 850 uptr GetMaxVirtualAddress() { 851 #if SANITIZER_WORDSIZE == 64 852 # if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM 853 // Get the maximum VM address 854 static uptr max_vm = GetTaskInfoMaxAddress(); 855 CHECK(max_vm); 856 return max_vm; 857 # else 858 return (1ULL << 47) - 1; // 0x00007fffffffffffUL; 859 # endif 860 #else // SANITIZER_WORDSIZE == 32 861 return (1ULL << 32) - 1; // 0xffffffff; 862 #endif // SANITIZER_WORDSIZE 863 } 864 865 uptr FindAvailableMemoryRange(uptr shadow_size, 866 uptr alignment, 867 uptr left_padding, 868 uptr *largest_gap_found) { 869 typedef vm_region_submap_short_info_data_64_t RegionInfo; 870 enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 }; 871 // Start searching for available memory region past PAGEZERO, which is 872 // 4KB on 32-bit and 4GB on 64-bit. 873 mach_vm_address_t start_address = 874 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000; 875 876 mach_vm_address_t address = start_address; 877 mach_vm_address_t free_begin = start_address; 878 kern_return_t kr = KERN_SUCCESS; 879 if (largest_gap_found) *largest_gap_found = 0; 880 while (kr == KERN_SUCCESS) { 881 mach_vm_size_t vmsize = 0; 882 natural_t depth = 0; 883 RegionInfo vminfo; 884 mach_msg_type_number_t count = kRegionInfoSize; 885 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth, 886 (vm_region_info_t)&vminfo, &count); 887 if (free_begin != address) { 888 // We found a free region [free_begin..address-1]. 889 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment); 890 uptr gap_end = RoundDownTo((uptr)address, alignment); 891 uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0; 892 if (shadow_size < gap_size) { 893 return gap_start; 894 } 895 896 if (largest_gap_found && *largest_gap_found < gap_size) { 897 *largest_gap_found = gap_size; 898 } 899 } 900 // Move to the next region. 901 address += vmsize; 902 free_begin = address; 903 } 904 905 // We looked at all free regions and could not find one large enough. 906 return 0; 907 } 908 909 // FIXME implement on this platform. 910 void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { } 911 912 void SignalContext::DumpAllRegisters(void *context) { 913 Report("Register values:\n"); 914 915 ucontext_t *ucontext = (ucontext_t*)context; 916 # define DUMPREG64(r) \ 917 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r); 918 # define DUMPREG32(r) \ 919 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r); 920 # define DUMPREG_(r) Printf(" "); DUMPREG(r); 921 # define DUMPREG__(r) Printf(" "); DUMPREG(r); 922 # define DUMPREG___(r) Printf(" "); DUMPREG(r); 923 924 # if defined(__x86_64__) 925 # define DUMPREG(r) DUMPREG64(r) 926 DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n"); 927 DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n"); 928 DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n"); 929 DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n"); 930 # elif defined(__i386__) 931 # define DUMPREG(r) DUMPREG32(r) 932 DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n"); 933 DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n"); 934 # elif defined(__aarch64__) 935 # define DUMPREG(r) DUMPREG64(r) 936 DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n"); 937 DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n"); 938 DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n"); 939 DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n"); 940 DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n"); 941 DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n"); 942 DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n"); 943 DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n"); 944 # elif defined(__arm__) 945 # define DUMPREG(r) DUMPREG32(r) 946 DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n"); 947 DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n"); 948 DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n"); 949 DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n"); 950 # else 951 # error "Unknown architecture" 952 # endif 953 954 # undef DUMPREG64 955 # undef DUMPREG32 956 # undef DUMPREG_ 957 # undef DUMPREG__ 958 # undef DUMPREG___ 959 # undef DUMPREG 960 } 961 962 static inline bool CompareBaseAddress(const LoadedModule &a, 963 const LoadedModule &b) { 964 return a.base_address() < b.base_address(); 965 } 966 967 void FormatUUID(char *out, uptr size, const u8 *uuid) { 968 internal_snprintf(out, size, 969 "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-" 970 "%02X%02X%02X%02X%02X%02X>", 971 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], 972 uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], 973 uuid[12], uuid[13], uuid[14], uuid[15]); 974 } 975 976 void PrintModuleMap() { 977 Printf("Process module map:\n"); 978 MemoryMappingLayout memory_mapping(false); 979 InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128); 980 memory_mapping.DumpListOfModules(&modules); 981 InternalSort(&modules, modules.size(), CompareBaseAddress); 982 for (uptr i = 0; i < modules.size(); ++i) { 983 char uuid_str[128]; 984 FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid()); 985 Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(), 986 modules[i].max_executable_address(), modules[i].full_name(), 987 ModuleArchToString(modules[i].arch()), uuid_str); 988 } 989 Printf("End of module map.\n"); 990 } 991 992 void CheckNoDeepBind(const char *filename, int flag) { 993 // Do nothing. 994 } 995 996 // FIXME: implement on this platform. 997 bool GetRandom(void *buffer, uptr length, bool blocking) { 998 UNIMPLEMENTED(); 999 } 1000 1001 } // namespace __sanitizer 1002 1003 #endif // SANITIZER_MAC 1004