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 0a9667b0f5.
This commit is contained in:
Julian Lettner 2022-07-07 17:26:19 -07:00
parent 72d9390778
commit 7789c9afc1
14 changed files with 134 additions and 54 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -1016,6 +1016,7 @@ struct SignalContext {
};
void InitializePlatformEarly();
void MaybeReexec();
template <typename Fn>
class RunOnDestruction {

View File

@ -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,

View File

@ -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) {}

View File

@ -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];

View File

@ -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.

View File

@ -1094,6 +1094,10 @@ void InitializePlatformEarly() {
// Do nothing.
}
void MaybeReexec() {
// No need to re-exec on Windows.
}
void CheckASLR() {
// Do nothing
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -46,12 +46,7 @@ if config.host_os == 'Darwin':
# 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'