aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2023-07-13 14:13:09 +0200
committerDmitry Vyukov <dvyukov@google.com>2023-07-13 16:28:25 +0200
commit13771793965bcda8951d6bdda1ea4ace658eca11 (patch)
tree377a06a13db20c6d003cd875812428fae5db0fb6 /compiler-rt
parentd3140f9363878907a56474164a49148821571720 (diff)
downloadllvm-13771793965bcda8951d6bdda1ea4ace658eca11.zip
llvm-13771793965bcda8951d6bdda1ea4ace658eca11.tar.gz
llvm-13771793965bcda8951d6bdda1ea4ace658eca11.tar.bz2
sanitizer_common: initialize sanitizer runtimes lazily from signal interceptors
Currently if a program calls sigaction very early (before non-lazy sanitizer initialization, in particular if .preinit_array initialization is not enabled), then sigaction will wrongly fail since the interceptor is not initialized yet. In all other interceptors we do lazy runtime initialization for this reason, but we don't do it in the signal interceptors. Do lazy runtime initialization in signal interceptors as well. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D155188
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cpp2
-rw-r--r--compiler-rt/lib/lsan/lsan_interceptors.cpp1
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cpp2
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc3
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp2
-rw-r--r--compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp5
-rw-r--r--compiler-rt/test/asan/lit.cfg.py44
-rw-r--r--compiler-rt/test/lit.common.cfg.py43
-rw-r--r--compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp21
9 files changed, 79 insertions, 44 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index b7e162c..b9b8256 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -194,6 +194,8 @@ static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
__lsan::ScopedInterceptorDisabler disabler
#endif
+#define SIGNAL_INTERCEPTOR_ENTER() ENSURE_ASAN_INITED()
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cpp b/compiler-rt/lib/lsan/lsan_interceptors.cpp
index ade9dfd..fac6133 100644
--- a/compiler-rt/lib/lsan/lsan_interceptors.cpp
+++ b/compiler-rt/lib/lsan/lsan_interceptors.cpp
@@ -533,6 +533,7 @@ INTERCEPTOR(void, _exit, int status) {
}
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#define SIGNAL_INTERCEPTOR_ENTER() ENSURE_LSAN_INITED
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
#endif // SANITIZER_POSIX
diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp
index 18a54f8..f5e0d3c 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cpp
+++ b/compiler-rt/lib/msan/msan_interceptors.cpp
@@ -1441,6 +1441,8 @@ static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
return REAL(func)(signo, handler); \
}
+#define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
+
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc
index 475e577..94e4e29 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc
@@ -43,6 +43,7 @@ using namespace __sanitizer;
#if SANITIZER_INTERCEPT_BSD_SIGNAL
INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
+ SIGNAL_INTERCEPTOR_ENTER();
if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
}
@@ -53,6 +54,7 @@ INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
#if SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
INTERCEPTOR(uptr, signal, int signum, uptr handler) {
+ SIGNAL_INTERCEPTOR_ENTER();
if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
return (uptr) nullptr;
SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
@@ -61,6 +63,7 @@ INTERCEPTOR(uptr, signal, int signum, uptr handler) {
INTERCEPTOR(int, sigaction_symname, int signum,
const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
+ SIGNAL_INTERCEPTOR_ENTER();
if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {
if (!oldact) return 0;
act = nullptr;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 44d20e7..177e338 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -2543,6 +2543,8 @@ static __sanitizer_sighandler_ptr signal_impl(int sig,
#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
{ return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
+#define SIGNAL_INTERCEPTOR_ENTER() LazyInitialize(cur_thread_init())
+
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
int sigaction_impl(int sig, const __sanitizer_sigaction *act,
diff --git a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp
index 2c91db8..354f847 100644
--- a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp
@@ -34,7 +34,12 @@ void InitializeDeadlySignals() {}
#else
+namespace __ubsan {
+void InitializeDeadlySignals();
+} // namespace __ubsan
+
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#define SIGNAL_INTERCEPTOR_ENTER() __ubsan::InitializeDeadlySignals()
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
// TODO(yln): Temporary workaround. Will be removed.
diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py
index e245a61..d930346 100644
--- a/compiler-rt/test/asan/lit.cfg.py
+++ b/compiler-rt/test/asan/lit.cfg.py
@@ -18,41 +18,6 @@ def get_required_attr(config, attr_name):
)
return attr_value
-
-def push_dynamic_library_lookup_path(config, new_path):
- if platform.system() == "Windows":
- dynamic_library_lookup_var = "PATH"
- elif platform.system() == "Darwin":
- dynamic_library_lookup_var = "DYLD_LIBRARY_PATH"
- else:
- dynamic_library_lookup_var = "LD_LIBRARY_PATH"
-
- new_ld_library_path = os.path.pathsep.join(
- (new_path, config.environment.get(dynamic_library_lookup_var, ""))
- )
- config.environment[dynamic_library_lookup_var] = new_ld_library_path
-
- if platform.system() == "FreeBSD":
- dynamic_library_lookup_var = "LD_32_LIBRARY_PATH"
- new_ld_32_library_path = os.path.pathsep.join(
- (new_path, config.environment.get(dynamic_library_lookup_var, ""))
- )
- config.environment[dynamic_library_lookup_var] = new_ld_32_library_path
-
- if platform.system() == "SunOS":
- dynamic_library_lookup_var = "LD_LIBRARY_PATH_32"
- new_ld_library_path_32 = os.path.pathsep.join(
- (new_path, config.environment.get(dynamic_library_lookup_var, ""))
- )
- config.environment[dynamic_library_lookup_var] = new_ld_library_path_32
-
- dynamic_library_lookup_var = "LD_LIBRARY_PATH_64"
- new_ld_library_path_64 = os.path.pathsep.join(
- (new_path, config.environment.get(dynamic_library_lookup_var, ""))
- )
- config.environment[dynamic_library_lookup_var] = new_ld_library_path_64
-
-
# Setup config name.
config.name = "AddressSanitizer" + config.name_suffix
@@ -285,15 +250,6 @@ if (
):
config.available_features.add("leak-detection")
-# Set LD_LIBRARY_PATH to pick dynamic runtime up properly.
-push_dynamic_library_lookup_path(config, config.compiler_rt_libdir)
-
-# GCC-ASan uses dynamic runtime by default.
-if config.compiler_id == "GNU":
- gcc_dir = os.path.dirname(config.clang)
- libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
- push_dynamic_library_lookup_path(config, libasan_dir)
-
# Add the RT libdir to PATH directly so that we can successfully run the gtest
# binary to list its tests.
if config.host_os == "Windows" and config.asan_dynamic:
diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py
index 24473f3..3b42da1 100644
--- a/compiler-rt/test/lit.common.cfg.py
+++ b/compiler-rt/test/lit.common.cfg.py
@@ -76,6 +76,40 @@ def find_compiler_libdir():
return None
+def push_dynamic_library_lookup_path(config, new_path):
+ if platform.system() == "Windows":
+ dynamic_library_lookup_var = "PATH"
+ elif platform.system() == "Darwin":
+ dynamic_library_lookup_var = "DYLD_LIBRARY_PATH"
+ else:
+ dynamic_library_lookup_var = "LD_LIBRARY_PATH"
+
+ new_ld_library_path = os.path.pathsep.join(
+ (new_path, config.environment.get(dynamic_library_lookup_var, ""))
+ )
+ config.environment[dynamic_library_lookup_var] = new_ld_library_path
+
+ if platform.system() == "FreeBSD":
+ dynamic_library_lookup_var = "LD_32_LIBRARY_PATH"
+ new_ld_32_library_path = os.path.pathsep.join(
+ (new_path, config.environment.get(dynamic_library_lookup_var, ""))
+ )
+ config.environment[dynamic_library_lookup_var] = new_ld_32_library_path
+
+ if platform.system() == "SunOS":
+ dynamic_library_lookup_var = "LD_LIBRARY_PATH_32"
+ new_ld_library_path_32 = os.path.pathsep.join(
+ (new_path, config.environment.get(dynamic_library_lookup_var, ""))
+ )
+ config.environment[dynamic_library_lookup_var] = new_ld_library_path_32
+
+ dynamic_library_lookup_var = "LD_LIBRARY_PATH_64"
+ new_ld_library_path_64 = os.path.pathsep.join(
+ (new_path, config.environment.get(dynamic_library_lookup_var, ""))
+ )
+ config.environment[dynamic_library_lookup_var] = new_ld_library_path_64
+
+
# Choose between lit's internal shell pipeline runner and a real shell. If
# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
@@ -895,3 +929,12 @@ if config.host_os == "Darwin":
# related is likely to cause issues with sanitizer tests, because it may
# preempt something we're looking to trap (e.g. _FORTIFY_SOURCE vs our ASAN).
config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1"
+
+# Set LD_LIBRARY_PATH to pick dynamic runtime up properly.
+push_dynamic_library_lookup_path(config, config.compiler_rt_libdir)
+
+# GCC-ASan uses dynamic runtime by default.
+if config.compiler_id == "GNU":
+ gcc_dir = os.path.dirname(config.clang)
+ libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
+ push_dynamic_library_lookup_path(config, libasan_dir)
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp b/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
new file mode 100644
index 0000000..95e0cef
--- /dev/null
+++ b/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
@@ -0,0 +1,21 @@
+// RUN: %clangxx -fsanitize=undefined -shared-libsan %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// Ensure ubsan runtime/interceptors are lazily initialized if called early.
+
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+
+__attribute__((constructor(0))) void ctor() {
+ fprintf(stderr, "INIT\n");
+ struct sigaction old;
+ assert(!sigaction(SIGSEGV, nullptr, &old));
+};
+
+int main() {
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: INIT
+// CHECK: DONE