From 76cc55a94d40c07463cd251e4b016cdeb9470474 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Mon, 6 Jul 2015 19:07:55 +0000 Subject: [PATCH] [asan] Add OS X 10.11's new dyld interposition support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On OS X 10.11 (which is currently a public beta), the dynamic linker has been improved so that it doesn't require the use of DYLD_INSERT_LIBRARIES in order for interposition/wrappers to work. This patch adds support of this behavior into ASan – we no longer need to re-exec in case the env. variable is not set. Reviewed at http://reviews.llvm.org/D10924 llvm-svn: 241487 --- compiler-rt/lib/asan/asan_mac.cc | 26 +++++++++++++++++-- .../Darwin/dyld_insert_libraries_reexec.cc | 18 +++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 37ec51ccb8a2..3e028378df28 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -99,6 +99,23 @@ void DisableReexec() { reexec_disabled = true; } +bool DyldNeedsEnvVariable() { +// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if +// DYLD_INSERT_LIBRARIES is not set. + +#if SANITIZER_IOSSIM + // GetMacosVersion will not work for the simulator, whose kernel version + // is tied to the host. Use a weak linking hack for the simulator. + // This API was introduced in the same version of the OS as the dyld + // optimization. + + // Check for presence of a symbol that is available on OS X 10.11+, iOS 9.0+. + return (dlsym(RTLD_NEXT, "mach_memory_info") == nullptr); +#else + return (GetMacosVersion() <= MACOS_VERSION_YOSEMITE); +#endif +} + void MaybeReexec() { if (reexec_disabled) return; @@ -114,8 +131,10 @@ void MaybeReexec() { uptr fname_len = internal_strlen(info.dli_fname); const char *dylib_name = StripModuleName(info.dli_fname); uptr dylib_name_len = internal_strlen(dylib_name); - if (!dyld_insert_libraries || - !REAL(strstr)(dyld_insert_libraries, dylib_name)) { + + bool lib_is_in_env = + dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name); + if (DyldNeedsEnvVariable() && !lib_is_in_env) { // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime // library. char program_name[1024]; @@ -152,6 +171,9 @@ void MaybeReexec() { CHECK("execv failed" && 0); } + if (!lib_is_in_env) + return; + // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove // the dylib from the environment variable, because interceptors are installed // and we don't want our children to inherit the variable. diff --git a/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc b/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc index 9210bafda8d5..486223473d47 100644 --- a/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc +++ b/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc @@ -7,11 +7,25 @@ // RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \ // RUN: %T/dyld_insert_libraries_reexec/libclang_rt.asan_osx_dynamic.dylib // RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_reexec/a.out + // RUN: env DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib \ // RUN: ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \ // RUN: | FileCheck %s -// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s + +// RUN: IS_OSX_10_11_OR_HIGHER=$([ `sw_vers -productVersion | cut -d'.' -f2` -lt 11 ]; echo $?) + +// On OS X 10.10 and lower, if the dylib is not DYLD-inserted, ASan will re-exec. +// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 0 ]; then \ +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s; \ +// RUN: fi + +// On OS X 10.11 and higher, we don't need to DYLD-insert anymore, and the interceptors +// still installed correctly. Let's just check that things work and we don't try to re-exec. +// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 1 ]; then \ +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \ +// RUN: | FileCheck %s; \ +// RUN: fi #include