diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp index d4811ff4ed217..bf861063ca1f5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -1298,6 +1298,29 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, return 0; } +// Returns true if the address is definitely mapped, and false if it is not +// mapped or could not be determined. +bool IsAddressInMappedRegion(uptr addr) { + mach_vm_size_t vmsize = 0; + natural_t depth = 0; + vm_region_submap_short_info_data_64_t vminfo; + mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; + mach_vm_address_t address = addr; + + kern_return_t kr = + mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth, + (vm_region_info_t)&vminfo, &count); + + if (kr == KERN_DENIED) { + Report( + "WARN: mach_vm_region_recurse returned KERN_DENIED when checking " + "whether an address is mapped.\n"); + Report("HINT: Is mach_vm_region_recurse allowed by sandbox?\n"); + } + + return (kr == KERN_SUCCESS && addr >= address && addr < address + vmsize); +} + // FIXME implement on this platform. void GetMemoryProfile(fill_profile_f cb, uptr *stats) {} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.h b/compiler-rt/lib/sanitizer_common/sanitizer_mac.h index b0e4ac7f40745..789dd8e4d8e9c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.h @@ -76,6 +76,8 @@ struct ThreadEventCallbacks { void InstallPthreadIntrospectionHook(const ThreadEventCallbacks &callbacks); +bool IsAddressInMappedRegion(uptr addr); + } // namespace __sanitizer #endif // SANITIZER_APPLE diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp index eb344df168ab9..5cc81bab5b911 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp @@ -226,9 +226,19 @@ static void ThreadTerminateCallback(uptr thread) { void InitializePlatformEarly() { # if !SANITIZER_GO && SANITIZER_IOS uptr max_vm = GetMaxUserVirtualAddress() + 1; - if (max_vm != HiAppMemEnd()) { - Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n", - (void *)max_vm, (void *)HiAppMemEnd()); + if (max_vm < HiAppMemEnd()) { + Report( + "ThreadSanitizer: Unsupported virtual memory layout:\n\tVM address " + "limit = %p\n\tExpected %p.\n", + (void*)max_vm, (void*)HiAppMemEnd()); + Die(); + } + // In some configurations, the max_vm is expanded, but much of this space is + // already mapped. TSAN will not work in this configuration. + if (IsAddressInMappedRegion(HiAppMemEnd() - 1)) { + Report( + "ThreadSanitizer: Unsupported virtual memory layout: Address %p is " + "already mapped.\n"); Die(); } #endif