summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2018-07-01 17:52:41 +0000
committerFangrui Song <maskray@google.com>2018-07-01 17:52:41 +0000
commit1da06fc8d37ff2abd1da1746e4066d7fd4eaeb07 (patch)
treeb4ceac9434f044a8f012aa3b617fe3d7f329c350 /lib
parent6758db1bffbd51069a083633d50252ad68be181e (diff)
[asan] Fix deadlock issue on FreeBSD, caused by use of .preinit_array in rL325240
Summary: Without this patch, clang -fsanitize=address -xc =(printf 'int main(){}') -o a; ./a => deadlock in __asan_init>AsanInitInternal>AsanTSDInit>...>__getcontextx_size>_rtld_bind>rlock_acquire(rtld_bind_lock, &lockstate) libexec/rtld-elf/rtld.c wlock_acquire(rtld_bind_lock, &lockstate); if (obj_main->crt_no_init) preinit_main(); // unresolved PLT functions cannot be called here lib/libthr/thread/thr_rtld.c uc_len = __getcontextx_size(); // unresolved PLT function in libthr.so.3 check-xray tests currently rely on .preinit_array so we special case in xray_init.cc Subscribers: srhines, kubamracek, krytarowski, delcypher, llvm-commits, #sanitizers Differential Revision: https://reviews.llvm.org/D48806 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@336067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/sanitizer_common/sanitizer_internal_defs.h11
-rw-r--r--lib/xray/xray_init.cc8
2 files changed, 15 insertions, 4 deletions
diff --git a/lib/sanitizer_common/sanitizer_internal_defs.h b/lib/sanitizer_common/sanitizer_internal_defs.h
index af2a821d7..a955733fb 100644
--- a/lib/sanitizer_common/sanitizer_internal_defs.h
+++ b/lib/sanitizer_common/sanitizer_internal_defs.h
@@ -98,11 +98,16 @@
// We can use .preinit_array section on Linux to call sanitizer initialization
// functions very early in the process startup (unless PIC macro is defined).
+//
+// On FreeBSD, .preinit_array functions are called with rtld_bind_lock writer
+// lock held. It will lead to dead lock if unresolved PLT functions (which helds
+// rtld_bind_lock reader lock) are called inside .preinit_array functions.
+//
// FIXME: do we have anything like this on Mac?
#ifndef SANITIZER_CAN_USE_PREINIT_ARRAY
-#if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || \
- SANITIZER_FREEBSD || SANITIZER_OPENBSD) && !defined(PIC)
-# define SANITIZER_CAN_USE_PREINIT_ARRAY 1
+#if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_OPENBSD) && \
+ !defined(PIC)
+#define SANITIZER_CAN_USE_PREINIT_ARRAY 1
// Before Solaris 11.4, .preinit_array is fully supported only with GNU ld.
// FIXME: Check for those conditions.
#elif SANITIZER_SOLARIS && !defined(PIC)
diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc
index 7f2610527..b4e069795 100644
--- a/lib/xray/xray_init.cc
+++ b/lib/xray/xray_init.cc
@@ -84,7 +84,13 @@ void __xray_init() XRAY_NEVER_INSTRUMENT {
#endif
}
-#if !defined(XRAY_NO_PREINIT) && SANITIZER_CAN_USE_PREINIT_ARRAY
+// FIXME: Make check-xray tests work on FreeBSD without
+// SANITIZER_CAN_USE_PREINIT_ARRAY.
+// See sanitizer_internal_defs.h where the macro is defined.
+// Calling unresolved PLT functions in .preinit_array can lead to deadlock on
+// FreeBSD but here it seems benign.
+#if !defined(XRAY_NO_PREINIT) && \
+ (SANITIZER_CAN_USE_PREINIT_ARRAY || SANITIZER_FREEBSD)
// Only add the preinit array initialization if the sanitizers can.
__attribute__((section(".preinit_array"),
used)) void (*__local_xray_preinit)(void) = __xray_init;