Skip to content

Commit 0ea0e3a

Browse files
authored
[sanitizer] Add CHECK that static TLS info is ready (#108684)
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`.
1 parent 8ee685e commit 0ea0e3a

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
130130
DTLS::DTV *dtv = DTLS_Find(dso_id);
131131
if (!dtv || dtv->beg)
132132
return nullptr;
133+
CHECK_LE(static_tls_begin, static_tls_end);
133134
uptr tls_size = 0;
134135
uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
135136
VReport(2,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Test that we don't crash accessing DTLS from malloc hook.
2+
3+
// RUN: %clang %s -o %t
4+
// RUN: %clang %s -DBUILD_SO -fPIC -o %t-so.so -shared
5+
// RUN: %run %t 2>&1 | FileCheck %s
6+
7+
// REQUIRES: glibc
8+
9+
// No allocator and hooks.
10+
// XFAIL: ubsan
11+
12+
// FIXME: Crashes on CHECK.
13+
// XFAIL: asan && !i386-linux
14+
// XFAIL: msan && !i386-linux
15+
16+
#ifndef BUILD_SO
17+
# include <assert.h>
18+
# include <dlfcn.h>
19+
# include <pthread.h>
20+
# include <stdio.h>
21+
# include <stdlib.h>
22+
23+
typedef long *(*get_t)();
24+
get_t GetTls;
25+
void *Thread(void *unused) { return GetTls(); }
26+
27+
__thread long recursive_hook;
28+
29+
// CHECK: __sanitizer_malloc_hook:
30+
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz)
31+
__attribute__((disable_sanitizer_instrumentation)) {
32+
++recursive_hook;
33+
if (recursive_hook == 1 && GetTls)
34+
fprintf(stderr, "__sanitizer_malloc_hook: %p\n", GetTls());
35+
--recursive_hook;
36+
}
37+
38+
int main(int argc, char *argv[]) {
39+
char path[4096];
40+
snprintf(path, sizeof(path), "%s-so.so", argv[0]);
41+
int i;
42+
43+
void *handle = dlopen(path, RTLD_LAZY);
44+
if (!handle)
45+
fprintf(stderr, "%s\n", dlerror());
46+
assert(handle != 0);
47+
GetTls = (get_t)dlsym(handle, "GetTls");
48+
assert(dlerror() == 0);
49+
50+
pthread_t t;
51+
pthread_create(&t, 0, Thread, 0);
52+
pthread_join(t, 0);
53+
pthread_create(&t, 0, Thread, 0);
54+
pthread_join(t, 0);
55+
return 0;
56+
}
57+
#else // BUILD_SO
58+
__thread long huge_thread_local_array[1 << 17];
59+
long *GetTls() { return &huge_thread_local_array[0]; }
60+
#endif

0 commit comments

Comments
 (0)