[llvm-branch-commits] [sanitizer] Add CHECK that static TLS info is ready (PR #108684)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Sep 13 23:02:17 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Vitaly Buka (vitalybuka)

<details>
<summary>Changes</summary>

There is possibility of
static_tls_begin is set and static_tls_end is not yet

The test reproduces the case.
Stack trace looks like this:
   `MsanThread::Init`
   `SetThreadStackAndTls`
   `GetThreadStackAndTls`
   `GetThreadStackTopAndBottom`
   `pthread_getattr_np`
   `realloc`
   `__sanitizer_malloc_hook`
   TLS access
   `___interceptor___tls_get_addr`
   `DTLS_on_tls_get_addr`

The issue is that `SetThreadStackAndTls` implementation
stores `tls_begin` before `GetThreadStackTopAndBottom`,
and `tls_end` after. So we have partially initialized
state in `DTLS_on_tls_get_addr`.


---
Full diff: https://github.com/llvm/llvm-project/pull/108684.diff


2 Files Affected:

- (modified) compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp (+1) 
- (added) compiler-rt/test/sanitizer_common/TestCases/Linux/tls_malloc_hook.c (+60) 


``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
index 087bd801b6e5ff..a17a14882d0e15 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
@@ -130,6 +130,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
   DTLS::DTV *dtv = DTLS_Find(dso_id);
   if (!dtv || dtv->beg)
     return nullptr;
+  CHECK_LE(static_tls_begin, static_tls_end);
   uptr tls_size = 0;
   uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
   VReport(2,
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_malloc_hook.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_malloc_hook.c
new file mode 100644
index 00000000000000..c582372ab9763d
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_malloc_hook.c
@@ -0,0 +1,60 @@
+// Test that we don't crash accessing DTLS from malloc hook.
+
+// RUN: %clang %s -o %t
+// RUN: %clang %s -DBUILD_SO -fPIC -o %t-so.so -shared
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: glibc
+
+// No allocator and hooks.
+// XFAIL: ubsan
+
+// FIXME: Crashes on CHECK.
+// XFAIL: asan && !i386-linux
+// XFAIL: msan && !i386-linux
+
+#ifndef BUILD_SO
+#  include <assert.h>
+#  include <dlfcn.h>
+#  include <pthread.h>
+#  include <stdio.h>
+#  include <stdlib.h>
+
+typedef long *(*get_t)();
+get_t GetTls;
+void *Thread(void *unused) { return GetTls(); }
+
+__thread long recursive_hook;
+
+// CHECK: __sanitizer_malloc_hook:
+void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz)
+    __attribute__((disable_sanitizer_instrumentation)) {
+  ++recursive_hook;
+  if (recursive_hook == 1 && GetTls)
+    fprintf(stderr, "__sanitizer_malloc_hook: %p\n", GetTls());
+  --recursive_hook;
+}
+
+int main(int argc, char *argv[]) {
+  char path[4096];
+  snprintf(path, sizeof(path), "%s-so.so", argv[0]);
+  int i;
+
+  void *handle = dlopen(path, RTLD_LAZY);
+  if (!handle)
+    fprintf(stderr, "%s\n", dlerror());
+  assert(handle != 0);
+  GetTls = (get_t)dlsym(handle, "GetTls");
+  assert(dlerror() == 0);
+
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  pthread_join(t, 0);
+  pthread_create(&t, 0, Thread, 0);
+  pthread_join(t, 0);
+  return 0;
+}
+#else // BUILD_SO
+__thread long huge_thread_local_array[1 << 17];
+long *GetTls() { return &huge_thread_local_array[0]; }
+#endif

``````````

</details>


https://github.com/llvm/llvm-project/pull/108684


More information about the llvm-branch-commits mailing list