[compiler-rt] r237495 - [sanitizer] Recognize static TLS in __tls_get_addr interceptor.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Fri May 15 17:34:15 PDT 2015


Author: eugenis
Date: Fri May 15 19:34:15 2015
New Revision: 237495

URL: http://llvm.org/viewvc/llvm-project?rev=237495&view=rev
Log:
[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.


Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri May 15 19:34:15 2015
@@ -182,6 +182,13 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free,
   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

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Fri May 15 19:34:15 2015
@@ -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)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Fri May 15 19:34:15 2015
@@ -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
   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);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc Fri May 15 19:34:15 2015
@@ -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 *ar
     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;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.h?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.h Fri May 15 19:34:15 2015
@@ -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.

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=237495&r1=237494&r2=237495&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri May 15 19:34:15 2015
@@ -2285,6 +2285,14 @@ static void HandleRecvmsg(ThreadState *t
   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() \

Added: compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc?rev=237495&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc Fri May 15 19:34:15 2015
@@ -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





More information about the llvm-commits mailing list