This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][GCC 5][PR sanitizer/69147] Fix ASan failures on new Darwin platforms (OS X 10.11+, iOS 9.0+).


Hi,

in OS X 10.11+ or iOS 9.0+, dyld will interpose even if DYLD_INSERT_LIBRARIES is not set. This means, that it's not safe to use "setenv" function to set DYLD_INSERT_LIBRARIES in MaybeReexec, because ASan interceptors already established and we can easily end up with something like this:

AsanInitInternal -> MaybeReexec -> setenv -> some intercepted function (say, memmove) -> BOOM.

In fact, there is no need to reexec at all on such platforms, because we already have working interceptors. Thus, for now we have completely broken ASan for OS X 10.11+ and iOS 9.0+ with GCC 5.

Upstream ASan already has a fix for the issue, as well as GCC 6, so the proper solution would be just cherry-picking corresponding commits (r224315 and r241487) from upstream to gcc-5-branch.

Regtested and bootstrapped on x86_64-unknown-linux-gnu by myself and on x86_64-apple-darwin15.2.0 by Dominique (https://gcc.gnu.org/ml/gcc-testresults/2016-01/msg01115.html).

Ok for gcc-5-branch?

-Maxim
libsanitizer/ChangeLog:

2016-01-13  Maxim Ostapenko  <m.ostapenko@partner.samsung.com>

	* PR sanitizer/69147
	* asan/asan_mac.cc: Cherry pick upstream r241487.
	* sanitizer_common/sanitizer_mac.cc: Cherry pick upstream r224315.
	* sanitizer_common/sanitizer_mac.h: Likewise.

diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc
index 70823bd..22f3f70 100644
--- a/libsanitizer/asan/asan_mac.cc
+++ b/libsanitizer/asan/asan_mac.cc
@@ -99,6 +99,23 @@ void LeakyResetEnv(const char *name, const char *name_value) {
   }
 }
 
+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 (!flags()->allow_reexec) return;
   // Make sure the dynamic ASan runtime library is preloaded so that the
@@ -111,8 +128,9 @@ void MaybeReexec() {
   uptr old_env_len = dyld_insert_libraries ?
       internal_strlen(dyld_insert_libraries) : 0;
   uptr fname_len = internal_strlen(info.dli_fname);
-  if (!dyld_insert_libraries ||
-      !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) {
+  bool lib_is_in_env =
+      dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, info.dli_fname);
+  if (DyldNeedsEnvVariable() && !lib_is_in_env) {
     // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
     // library.
     char program_name[1024];
@@ -141,6 +159,10 @@ void MaybeReexec() {
     VReport(1, "Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n");
     execv(program_name, *_NSGetArgv());
   } else {
+
+    if (!lib_is_in_env)
+      return;
+
     // DYLD_INSERT_LIBRARIES is set and contains the runtime library.
     if (old_env_len == fname_len) {
       // It's just the runtime library name - fine to unset the variable.
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index 17b931c..b53ffba 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -296,7 +296,11 @@ MacosVersion GetMacosVersionInternal() {
         case '2': return MACOS_VERSION_MOUNTAIN_LION;
         case '3': return MACOS_VERSION_MAVERICKS;
         case '4': return MACOS_VERSION_YOSEMITE;
-        default: return MACOS_VERSION_UNKNOWN;
+        default:
+          if (IsDigit(version[1]))
+            return MACOS_VERSION_UNKNOWN_NEWER;
+          else
+            return MACOS_VERSION_UNKNOWN;
       }
     }
     default: return MACOS_VERSION_UNKNOWN;
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.h b/libsanitizer/sanitizer_common/sanitizer_mac.h
index 47739f7..46a7b44 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.h
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.h
@@ -25,6 +25,7 @@ enum MacosVersion {
   MACOS_VERSION_MOUNTAIN_LION,
   MACOS_VERSION_MAVERICKS,
   MACOS_VERSION_YOSEMITE,
+  MACOS_VERSION_UNKNOWN_NEWER
 };
 
 MacosVersion GetMacosVersion();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]