[compiler-rt] r348078 - Introduce a way to allow the ASan dylib on Darwin platforms to be loaded via `dlopen()`.
Dan Liew via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 1 07:45:42 PST 2018
Author: delcypher
Date: Sat Dec 1 07:45:42 2018
New Revision: 348078
URL: http://llvm.org/viewvc/llvm-project?rev=348078&view=rev
Log:
Introduce a way to allow the ASan dylib on Darwin platforms to be loaded via `dlopen()`.
Summary:
The purpose of this option is provide a way for the ASan dylib
to be loaded via `dlopen()` without triggering most initialization
steps (e.g. shadow memory set up) that normally occur when the
ASan dylib is loaded.
This new functionality is exposed by
- A `SANITIZER_SUPPORTS_INIT_FOR_DLOPEN` macro which indicates if the
feature is supported. This only true for Darwin currently.
- A `HandleDlopenInit()` function which should return true if the library
is being loaded via `dlopen()` and
`SANITIZER_SUPPORTS_INIT_FOR_DLOPEN` is supported. Platforms that
support this may perform any initialization they wish inside this
function.
Although disabling initialization is something that could potentially
apply to other sanitizers it appears to be unnecessary for other
sanitizers so this patch only makes the change for ASan.
rdar://problem/45284065
Reviewers: kubamracek, george.karpenkov, kcc, eugenis, krytarowski
Subscribers: #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D54469
Added:
compiler-rt/trunk/test/asan/TestCases/Darwin/init_for_dlopen.cc
Modified:
compiler-rt/trunk/lib/asan/asan_fuchsia.cc
compiler-rt/trunk/lib/asan/asan_internal.h
compiler-rt/trunk/lib/asan/asan_linux.cc
compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
compiler-rt/trunk/lib/asan/asan_rtems.cc
compiler-rt/trunk/lib/asan/asan_rtl.cc
compiler-rt/trunk/lib/asan/asan_win.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform.h
compiler-rt/trunk/test/sanitizer_common/ios_commands/iossim_run.py
Modified: compiler-rt/trunk/lib/asan/asan_fuchsia.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_fuchsia.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fuchsia.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_fuchsia.cc Sat Dec 1 07:45:42 2018
@@ -190,6 +190,13 @@ static void ThreadExitHook(void *hook, u
AsanThread::TSDDtor(per_thread);
}
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
} // namespace __asan
// These are declared (in extern "C") by <zircon/sanitizer.h>.
Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Sat Dec 1 07:45:42 2018
@@ -111,6 +111,11 @@ void *AsanDlSymNext(const char *sym);
void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name);
+// Returns `true` iff most of ASan init process should be skipped due to the
+// ASan library being loaded via `dlopen()`. Platforms may perform any
+// `dlopen()` specific initialization inside this function.
+bool HandleDlopenInit();
+
// Add convenient macro for interface functions that may be represented as
// weak hooks.
#define ASAN_MALLOC_HOOK(ptr, size) \
Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Sat Dec 1 07:45:42 2018
@@ -248,6 +248,13 @@ void *AsanDlSymNext(const char *sym) {
return dlsym(RTLD_NEXT, sym);
}
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
} // namespace __asan
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Sat Dec 1 07:45:42 2018
@@ -61,4 +61,25 @@ using namespace __asan;
#include "sanitizer_common/sanitizer_malloc_mac.inc"
+namespace COMMON_MALLOC_NAMESPACE {
+bool HandleDlopenInit() {
+ static_assert(SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be true");
+ // We have no reliable way of knowing how we are being loaded
+ // so make it a requirement on Apple platforms to set this environment
+ // variable to indicate that we want to perform initialization via
+ // dlopen().
+ auto init_str = GetEnv("APPLE_ASAN_INIT_FOR_DLOPEN");
+ if (!init_str)
+ return false;
+ if (internal_strncmp(init_str, "1", 1) != 0)
+ return false;
+ // When we are loaded via `dlopen()` path we still initialize the malloc zone
+ // so Symbolication clients (e.g. `leaks`) that load the ASan allocator can
+ // find an initialized malloc zone.
+ InitMallocZoneFields();
+ return true;
+}
+} // namespace COMMON_MALLOC_NAMESPACE
+
#endif
Modified: compiler-rt/trunk/lib/asan/asan_rtems.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtems.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtems.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtems.cc Sat Dec 1 07:45:42 2018
@@ -213,6 +213,12 @@ static void HandleExit() {
}
}
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
} // namespace __asan
// These are declared (in extern "C") by <some_path/sanitizer.h>.
Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Sat Dec 1 07:45:42 2018
@@ -396,6 +396,14 @@ static void AsanInitInternal() {
// initialization steps look at flags().
InitializeFlags();
+ // Stop performing init at this point if we are being loaded via
+ // dlopen() and the platform supports it.
+ if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {
+ asan_init_is_running = false;
+ VReport(1, "AddressSanitizer init is being performed for dlopen().\n");
+ return;
+ }
+
AsanCheckIncompatibleRT();
AsanCheckDynamicRTPrereqs();
AvoidCVE_2016_2143();
Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Sat Dec 1 07:45:42 2018
@@ -322,6 +322,13 @@ int __asan_set_seh_filter() {
return 0;
}
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
#if !ASAN_DYNAMIC
// The CRT runs initializers in this order:
// - C initializers, from XIA to XIZ
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform.h?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform.h Sat Dec 1 07:45:42 2018
@@ -342,4 +342,13 @@
#define SANITIZER_SYMBOLIZER_MARKUP 0
#endif
+// Enable ability to support sanitizer initialization that is
+// compatible with the sanitizer library being loaded via
+// `dlopen()`.
+#if SANITIZER_MAC
+#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 1
+#else
+#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
+#endif
+
#endif // SANITIZER_PLATFORM_H
Added: compiler-rt/trunk/test/asan/TestCases/Darwin/init_for_dlopen.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Darwin/init_for_dlopen.cc?rev=348078&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Darwin/init_for_dlopen.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Darwin/init_for_dlopen.cc Sat Dec 1 07:45:42 2018
@@ -0,0 +1,46 @@
+// RUN: %clangxx -g -O0 %s -o %t
+
+// Check that trying to dlopen() the ASan dylib fails.
+// We explictly set `abort_on_error=0` because
+// - By default the lit config sets this but we don't want this
+// test to implicitly depend on this.
+// - It avoids requiring `--crash` to be passed to `not`.
+// RUN: APPLE_ASAN_INIT_FOR_DLOPEN=0 %env_asan_opts=abort_on_error=0 not \
+// RUN: %run %t %shared_libasan 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-DL-OPEN-FAIL %s
+// RUN: env -u APPLE_ASAN_INIT_FOR_DLOPEN %env_asan_opts=abort_on_error=0 not \
+// RUN: %run %t %shared_libasan 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-DL-OPEN-FAIL %s
+
+// Check that we can successfully dlopen the ASan dylib when we set the right
+// environment variable.
+// RUN: env APPLE_ASAN_INIT_FOR_DLOPEN=1 %run %t %shared_libasan 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-DL-OPEN-SUCCESS %s
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+// CHECK-DL-OPEN-FAIL: ERROR: Interceptors are not working
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <dylib_path>\n", argv[0]);
+ return 1;
+ }
+ const char *dylib_path = argv[1];
+ void *handle = dlopen(dylib_path, RTLD_LAZY);
+ if (!handle) {
+ fprintf(stderr, "Failed to dlopen: %s\n", dlerror());
+ return 1;
+ }
+ // Make sure we can find a function we expect to be in the dylib.
+ void *fn = dlsym(handle, "__sanitizer_mz_size");
+ if (!fn) {
+ fprintf(stderr, "Failed to get symbol: %s\n", dlerror());
+ return 1;
+ }
+ // TODO(dliew): Actually call a function from the dylib that is safe to call.
+ // CHECK-DL-OPEN-SUCCESS: DONE
+ printf("DONE\n");
+ return 0;
+}
Modified: compiler-rt/trunk/test/sanitizer_common/ios_commands/iossim_run.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/ios_commands/iossim_run.py?rev=348078&r1=348077&r2=348078&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/ios_commands/iossim_run.py (original)
+++ compiler-rt/trunk/test/sanitizer_common/ios_commands/iossim_run.py Sat Dec 1 07:45:42 2018
@@ -8,7 +8,7 @@ if not "SANITIZER_IOSSIM_TEST_DEVICE_IDE
device_id = os.environ["SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER"]
-for e in ["ASAN_OPTIONS", "TSAN_OPTIONS", "UBSAN_OPTIONS"]:
+for e in ["ASAN_OPTIONS", "TSAN_OPTIONS", "UBSAN_OPTIONS", "APPLE_ASAN_INIT_FOR_DLOPEN"]:
if e in os.environ:
os.environ["SIMCTL_CHILD_" + e] = os.environ[e]
More information about the llvm-commits
mailing list