[compiler-rt] 7789c9a - Revert "[Sanitizer][Darwin] Cleanup MaybeReexec() function and usage"
Julian Lettner via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 7 17:27:17 PDT 2022
Author: Julian Lettner
Date: 2022-07-07T17:27:10-07:00
New Revision: 7789c9afc1237e409cddb83bf199231441851305
URL: https://github.com/llvm/llvm-project/commit/7789c9afc1237e409cddb83bf199231441851305
DIFF: https://github.com/llvm/llvm-project/commit/7789c9afc1237e409cddb83bf199231441851305.diff
LOG: Revert "[Sanitizer][Darwin] Cleanup MaybeReexec() function and usage"
Many tests for the `UBSan-Standalone-iossim-x86_64` fail with this.
Reverting so I can investigate.
This reverts commit 0a9667b0f56b1b450abd02f74c6175bea54f832e.
Added:
Modified:
compiler-rt/lib/asan/asan_rtl.cpp
compiler-rt/lib/asan/tests/asan_test_main.cpp
compiler-rt/lib/memprof/memprof_rtl.cpp
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
compiler-rt/lib/tsan/tests/rtl/tsan_test.cpp
compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cpp
compiler-rt/test/asan/TestCases/Darwin/init_for_dlopen.cpp
compiler-rt/unittests/lit.common.unit.cfg.py
Removed:
################################################################################
diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp
index 2bbf0ac5240a7..29cf526d9eb0b 100644
--- a/compiler-rt/lib/asan/asan_rtl.cpp
+++ b/compiler-rt/lib/asan/asan_rtl.cpp
@@ -421,6 +421,9 @@ static void AsanInitInternal() {
__sanitizer::InitializePlatformEarly();
+ // Re-exec ourselves if we need to set additional env or command line args.
+ MaybeReexec();
+
// Setup internal allocator callback.
SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY);
SetLowLevelAllocateCallback(OnLowLevelAllocate);
diff --git a/compiler-rt/lib/asan/tests/asan_test_main.cpp b/compiler-rt/lib/asan/tests/asan_test_main.cpp
index 136b752aebb0c..64ac1b288e53c 100644
--- a/compiler-rt/lib/asan/tests/asan_test_main.cpp
+++ b/compiler-rt/lib/asan/tests/asan_test_main.cpp
@@ -33,6 +33,21 @@ extern "C" const char* __asan_default_options() {
#endif
}
+namespace __sanitizer {
+bool ReexecDisabled() {
+#if __has_feature(address_sanitizer) && SANITIZER_APPLE
+ // Allow re-exec in instrumented unit tests on Darwin. Technically, we only
+ // need this for 10.10 and below, where re-exec is required for the
+ // interceptors to work, but to avoid duplicating the version detection logic,
+ // let's just allow re-exec for all Darwin versions. On newer OS versions,
+ // returning 'false' doesn't do anything anyway, because we don't re-exec.
+ return false;
+#else
+ return true;
+#endif
+}
+} // namespace __sanitizer
+
int main(int argc, char **argv) {
testing::GTEST_FLAG(death_test_style) = "threadsafe";
testing::InitGoogleTest(&argc, argv);
diff --git a/compiler-rt/lib/memprof/memprof_rtl.cpp b/compiler-rt/lib/memprof/memprof_rtl.cpp
index d568a075c3e18..21424fb4f0729 100644
--- a/compiler-rt/lib/memprof/memprof_rtl.cpp
+++ b/compiler-rt/lib/memprof/memprof_rtl.cpp
@@ -170,6 +170,9 @@ static void MemprofInitInternal() {
__sanitizer::InitializePlatformEarly();
+ // Re-exec ourselves if we need to set additional env or command line args.
+ MaybeReexec();
+
// Setup internal allocator callback.
SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 517f776baf6ef..345c262af9728 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -1016,6 +1016,7 @@ struct SignalContext {
};
void InitializePlatformEarly();
+void MaybeReexec();
template <typename Fn>
class RunOnDestruction {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
index 6148ae56067ca..8627ffd0d01c2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
@@ -68,12 +68,9 @@ COMMON_FLAG(
COMMON_FLAG(
int, verbosity, 0,
"Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
-COMMON_FLAG(bool, strip_env, true,
+COMMON_FLAG(bool, strip_env, 1,
"Whether to remove the sanitizer from DYLD_INSERT_LIBRARIES to "
- "avoid passing it to children on Apple platforms. Default is true.")
-COMMON_FLAG(bool, verify_interceptors, true,
- "Verify that interceptors are working on Apple platforms. Default "
- "is true.")
+ "avoid passing it to children. Default is true.")
COMMON_FLAG(bool, detect_leaks, !SANITIZER_APPLE, "Enable memory leak detection.")
COMMON_FLAG(
bool, leak_check_at_exit, true,
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
index a92e84cb8ecf7..e253b67fc484f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -87,6 +87,7 @@ void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) {
}
void InitializePlatformEarly() {}
+void MaybeReexec() {}
void CheckASLR() {}
void CheckMPROTECT() {}
void PlatformPrepareForSandboxing(void *args) {}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 86e2676a6acd1..f3fd70af81564 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -2180,6 +2180,10 @@ void InitializePlatformEarly() {
// Do nothing.
}
+void MaybeReexec() {
+ // No need to re-exec on Linux.
+}
+
void CheckASLR() {
#if SANITIZER_NETBSD
int mib[3];
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
index 9dc10612d4295..327c7167dcf5e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
@@ -943,9 +943,6 @@ static void DisableMmapExcGuardExceptions() {
set_behavior(mach_task_self(), task_exc_guard_none);
}
-static void VerifyInterceptorsWorking();
-static void StripEnv();
-
void InitializePlatformEarly() {
// Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
use_xnu_fast_mmap =
@@ -956,43 +953,17 @@ void InitializePlatformEarly() {
#endif
if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0))
DisableMmapExcGuardExceptions();
-
-# if !SANITIZER_GO
- MonotonicNanoTime(); // Call to initialize mach_timebase_info
- VerifyInterceptorsWorking();
- StripEnv();
-# endif
}
#if !SANITIZER_GO
static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
LowLevelAllocator allocator_for_env;
-static void VerifyInterceptorsWorking() {
- if (!common_flags()->verify_interceptors)
- return;
-
- // Verify that interceptors really work. We'll use dlsym to locate
- // "puts", if interceptors are working, it should really point to
- // "wrap_puts" within our own dylib.
- Dl_info info_puts, info_runtime;
- RAW_CHECK(dladdr(dlsym(RTLD_DEFAULT, "puts"), &info_puts));
- RAW_CHECK(dladdr((void *)__sanitizer_report_error_summary, &info_runtime));
- if (internal_strcmp(info_puts.dli_fname, info_runtime.dli_fname) != 0) {
- Report(
- "ERROR: Interceptors are not working. This may be because %s is "
- "loaded too late (e.g. via dlopen). Please launch the executable "
- "with:\n%s=%s\n",
- SanitizerToolName, kDyldInsertLibraries, info_runtime.dli_fname);
- RAW_CHECK("interceptors not installed" && 0);
- }
-}
-
// Change the value of the env var |name|, leaking the original value.
// If |name_value| is NULL, the variable is deleted from the environment,
// otherwise the corresponding "NAME=value" string is replaced with
// |name_value|.
-static void LeakyResetEnv(const char *name, const char *name_value) {
+void LeakyResetEnv(const char *name, const char *name_value) {
char **env = GetEnviron();
uptr name_len = internal_strlen(name);
while (*env != 0) {
@@ -1017,28 +988,100 @@ static void LeakyResetEnv(const char *name, const char *name_value) {
}
}
-static void StripEnv() {
- if (!common_flags()->strip_env)
- return;
+SANITIZER_WEAK_CXX_DEFAULT_IMPL
+bool ReexecDisabled() {
+ return false;
+}
- char *dyld_insert_libraries =
- const_cast<char *>(GetEnv(kDyldInsertLibraries));
- if (!dyld_insert_libraries)
- return;
+static bool DyldNeedsEnvVariable() {
+ // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
+ // DYLD_INSERT_LIBRARIES is not set.
+ return GetMacosAlignedVersion() < MacosVersion(10, 11);
+}
+
+void MaybeReexec() {
+ // FIXME: This should really live in some "InitializePlatform" method.
+ MonotonicNanoTime();
+ if (ReexecDisabled()) return;
+
+ // Make sure the dynamic runtime library is preloaded so that the
+ // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
+ // ourselves.
Dl_info info;
- RAW_CHECK(dladdr((void *)__sanitizer_report_error_summary, &info));
+ RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
+ char *dyld_insert_libraries =
+ const_cast<char*>(GetEnv(kDyldInsertLibraries));
+ uptr old_env_len = dyld_insert_libraries ?
+ internal_strlen(dyld_insert_libraries) : 0;
+ uptr fname_len = internal_strlen(info.dli_fname);
const char *dylib_name = StripModuleName(info.dli_fname);
- bool lib_is_in_env = internal_strstr(dyld_insert_libraries, dylib_name);
+ uptr dylib_name_len = internal_strlen(dylib_name);
+
+ bool lib_is_in_env = dyld_insert_libraries &&
+ internal_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.
+ InternalMmapVector<char> program_name(1024);
+ uint32_t buf_size = program_name.size();
+ _NSGetExecutablePath(program_name.data(), &buf_size);
+ char *new_env = const_cast<char*>(info.dli_fname);
+ if (dyld_insert_libraries) {
+ // Append the runtime dylib name to the existing value of
+ // DYLD_INSERT_LIBRARIES.
+ new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
+ internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
+ new_env[old_env_len] = ':';
+ // Copy fname_len and add a trailing zero.
+ internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
+ fname_len + 1);
+ // Ok to use setenv() since the wrappers don't depend on the value of
+ // asan_inited.
+ setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
+ } else {
+ // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
+ setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
+ }
+ VReport(1, "exec()-ing the program with\n");
+ VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
+ VReport(1, "to enable wrappers.\n");
+ execv(program_name.data(), *_NSGetArgv());
+
+ // We get here only if execv() failed.
+ Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
+ "which is required for the sanitizer to work. We tried to set the "
+ "environment variable and re-execute itself, but execv() failed, "
+ "possibly because of sandbox restrictions. Make sure to launch the "
+ "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
+ RAW_CHECK("execv failed" && 0);
+ }
+
+ // Verify that interceptors really work. We'll use dlsym to locate
+ // "puts", if interceptors are working, it should really point to
+ // "wrap_puts" within our own dylib.
+ Dl_info info_puts;
+ void *dlopen_addr = dlsym(RTLD_DEFAULT, "puts");
+ RAW_CHECK(dladdr(dlopen_addr, &info_puts));
+ if (internal_strcmp(info.dli_fname, info_puts.dli_fname) != 0) {
+ Report(
+ "ERROR: Interceptors are not working. This may be because %s is "
+ "loaded too late (e.g. via dlopen). Please launch the executable "
+ "with:\n%s=%s\n",
+ SanitizerToolName, kDyldInsertLibraries, info.dli_fname);
+ RAW_CHECK("interceptors not installed" && 0);
+ }
+
if (!lib_is_in_env)
return;
+ if (!common_flags()->strip_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.
- uptr old_env_len = internal_strlen(dyld_insert_libraries);
- uptr dylib_name_len = internal_strlen(dylib_name);
uptr env_name_len = internal_strlen(kDyldInsertLibraries);
// Allocate memory to hold the previous env var name, its value, the '='
// sign and the '\0' char.
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index b4506e52efaaf..c997514cfed7f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -1094,6 +1094,10 @@ void InitializePlatformEarly() {
// Do nothing.
}
+void MaybeReexec() {
+ // No need to re-exec on Windows.
+}
+
void CheckASLR() {
// Do nothing
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index 607f373871b44..3977d60c36e54 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -651,6 +651,9 @@ void Initialize(ThreadState *thr) {
__tsan::InitializePlatformEarly();
#if !SANITIZER_GO
+ // Re-exec ourselves if we need to set additional env or command line args.
+ MaybeReexec();
+
InitializeAllocator();
ReplaceSystemMalloc();
#endif
diff --git a/compiler-rt/lib/tsan/tests/rtl/tsan_test.cpp b/compiler-rt/lib/tsan/tests/rtl/tsan_test.cpp
index 477a41d98c1d2..594c3ebfeb738 100644
--- a/compiler-rt/lib/tsan/tests/rtl/tsan_test.cpp
+++ b/compiler-rt/lib/tsan/tests/rtl/tsan_test.cpp
@@ -53,6 +53,12 @@ extern "C" const char* __tsan_default_options() {
}
#endif
+namespace __sanitizer {
+bool ReexecDisabled() {
+ return true;
+}
+}
+
int main(int argc, char **argv) {
argv0 = argv[0];
return run_tests(argc, argv);
diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cpp b/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cpp
index fb01d3e923aa8..0e7b18a2ab3d3 100644
--- a/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cpp
+++ b/compiler-rt/lib/tsan/tests/unit/tsan_unit_test_main.cpp
@@ -11,6 +11,12 @@
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
+namespace __sanitizer {
+bool ReexecDisabled() {
+ return true;
+}
+}
+
int main(int argc, char **argv) {
testing::GTEST_FLAG(death_test_style) = "threadsafe";
testing::InitGoogleTest(&argc, argv);
diff --git a/compiler-rt/test/asan/TestCases/Darwin/init_for_dlopen.cpp b/compiler-rt/test/asan/TestCases/Darwin/init_for_dlopen.cpp
index 0107f30dd7d9b..8a0fbf943b672 100644
--- a/compiler-rt/test/asan/TestCases/Darwin/init_for_dlopen.cpp
+++ b/compiler-rt/test/asan/TestCases/Darwin/init_for_dlopen.cpp
@@ -21,7 +21,6 @@
#include <stdio.h>
// CHECK-DL-OPEN-FAIL: ERROR: Interceptors are not working
-// CHECK-SAME-DL-OPEN-FAIL: Please launch the executable with: DYLD_INSERT_LIBRARIES={{.+}}/libclang_rt.asan_{{.+}}_dynamic.dylib
int main(int argc, char **argv) {
if (argc != 2) {
diff --git a/compiler-rt/unittests/lit.common.unit.cfg.py b/compiler-rt/unittests/lit.common.unit.cfg.py
index dd6b5bab5b65d..c72b06d6b5f31 100644
--- a/compiler-rt/unittests/lit.common.unit.cfg.py
+++ b/compiler-rt/unittests/lit.common.unit.cfg.py
@@ -46,12 +46,7 @@ def get_lit_conf(name, default=None):
# 64-bit Darwin. Using more scales badly and hogs the system due to
# inefficient handling of large mmap'd regions (terabytes) by the kernel.
lit_config.parallelism_groups["shadow-memory"] = 3
-
- # Disable libmalloc nano allocator due to crashes running on macOS 12.0.
+ # Disable libmalloc nanoallocator due to crashes running on macOS 12.0.
+ #
# rdar://80086125
config.environment['MallocNanoZone'] = '0'
-
- # We crash when we set DYLD_INSERT_LIBRARIES for unit tests, so interceptors
- # don't work.
- config.environment['ASAN_OPTIONS'] = 'verify_interceptors=0'
- config.environment['TSAN_OPTIONS'] = 'verify_interceptors=0'
More information about the llvm-commits
mailing list