forked from OSchip/llvm-project
[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
This commit is contained in:
parent
1c299d05e6
commit
7f6290ca9a
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() \
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue