summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2015-05-16 00:34:15 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2015-05-16 00:34:15 +0000
commit7f6290ca9ab4b02eab67262a8a103473c9148acc (patch)
tree59dceb8d91390ca3e7fdb6f141fdb502b7af8ed5
parent1c299d05e6b75d5bdc87239aa7136773df44783e (diff)
downloadbcm5719-llvm-7f6290ca9ab4b02eab67262a8a103473c9148acc.tar.gz
bcm5719-llvm-7f6290ca9ab4b02eab67262a8a103473c9148acc.zip
[sanitizer] Recognize static TLS in __tls_get_addr interceptor.
Current code tries to find the dynamic TLS header to the left of the TLS block without checking that it's not a static TLS allocation. llvm-svn: 237495
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cc7
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cc8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h3
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc8
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/static_tls.cc27
7 files changed, 66 insertions, 3 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc
index 1318785bdc6..d8b48d391ab 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cc
+++ b/compiler-rt/lib/asan/asan_interceptors.cc
@@ -182,6 +182,13 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
CoverageUpdateMapping()
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (AsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
#include "sanitizer_common/sanitizer_common_interceptors.inc"
// Syscall interceptors don't have contexts, we don't support suppressions
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index a1e81931b22..ffae221cec4 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -1397,6 +1397,14 @@ int OnExit() {
if (map) ForEachMappedRegion(map, __msan_unpoison); \
} while (false)
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (MsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 6e81a50ec33..4df015408fb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -114,6 +114,10 @@
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {}
#endif
+#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
+#endif
+
struct FileMetadata {
// For open_memstream().
char **addr;
@@ -3996,7 +4000,9 @@ INTERCEPTOR(void *, __tls_get_addr, void *arg) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
void *res = REAL(__tls_get_addr)(arg);
- DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res);
+ uptr tls_begin, tls_end;
+ COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
if (dtv) {
// New DTLS block has been allocated.
COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc
index 6142ce517db..ea037159d00 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc
@@ -78,7 +78,8 @@ void DTLS_Destroy() {
DTLS_Deallocate(dtls.dtv, s);
}
-DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res) {
+DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
+ uptr static_tls_begin, uptr static_tls_end) {
if (!common_flags()->intercept_tls_get_addr) return 0;
TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
uptr dso_id = arg->dso_id;
@@ -95,6 +96,11 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res) {
tls_size = dtls.last_memalign_size;
VPrintf(2, "__tls_get_addr: glibc <=2.18 suspected; tls={%p,%p}\n",
tls_beg, tls_size);
+ } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
+ // This is the static TLS block which was initialized / unpoisoned at thread
+ // creation.
+ VPrintf(2, "__tls_get_addr: static tls: %p\n", tls_beg);
+ tls_size = 0;
} else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
// We may want to check gnu_get_libc_version().
Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h
index 0fc9a2257c6..58d47634d38 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h
@@ -50,7 +50,8 @@ struct DTLS {
// Returns pointer and size of a linker-allocated TLS block.
// Each block is returned exactly once.
-DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res);
+DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res, uptr static_tls_begin,
+ uptr static_tls_end);
void DTLS_on_libc_memalign(void *ptr, uptr size);
DTLS *DTLS_Get();
void DTLS_Destroy(); // Make sure to call this before the thread is destroyed.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index 36d93e0c4bd..b47332dc3e9 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -2285,6 +2285,14 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
((TsanInterceptorContext *)ctx)->pc, msg)
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (TsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define TSAN_SYSCALL() \
diff --git a/compiler-rt/test/asan/TestCases/Linux/static_tls.cc b/compiler-rt/test/asan/TestCases/Linux/static_tls.cc
new file mode 100644
index 00000000000..2b2bc41479c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Linux/static_tls.cc
@@ -0,0 +1,27 @@
+// REQUIRES: asan-64-bits
+// Regression test: __tls_get_addr interceptor must recognize static TLS.
+//
+// RUN: %clangxx_asan -DSHARED %s -shared -o %t-so.so -fPIC
+// RUN: %clangxx_asan %s -ldl -pthread -o %t %t-so.so
+// RUN: ASAN_OPTIONS=verbosity=2 %run %t 2>&1 | FileCheck %s
+
+// CHECK: before
+// CHECK: __tls_get_addr: static tls
+// CHECK: after
+
+#ifndef SHARED
+#include <stdio.h>
+
+unsigned *f();
+int main(int argc, char *argv[]) {
+ fprintf(stderr, "before\n");
+ f();
+ fprintf(stderr, "after\n");
+ return 0;
+}
+#else // SHARED
+static __thread unsigned ThreadLocal;
+unsigned *f() {
+ return &ThreadLocal;
+}
+#endif
OpenPOWER on IntegriCloud