Skip to content

[sanitizer] Fix partially initialized static TLS range #108685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler-rt/lib/asan/asan_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ bool PlatformUnpoisonStacks() {

// Since we're on the signal alternate stack, we cannot find the DEFAULT
// stack bottom using a local variable.
uptr default_bottom, tls_addr, tls_size, stack_size;
GetThreadStackAndTls(/*main=*/false, &default_bottom, &stack_size, &tls_addr,
&tls_size);
UnpoisonStack(default_bottom, default_bottom + stack_size, "default");
uptr stack_begin, stack_end, tls_begin, tls_end;
GetThreadStackAndTls(/*main=*/false, &stack_begin, &stack_end, &tls_begin,
&tls_end);
UnpoisonStack(stack_begin, stack_end, "default");
return true;
}

Expand Down
6 changes: 2 additions & 4 deletions compiler-rt/lib/asan/asan_rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,10 +580,8 @@ static void UnpoisonDefaultStack() {
} else {
CHECK(!SANITIZER_FUCHSIA);
// If we haven't seen this thread, try asking the OS for stack bounds.
uptr tls_addr, tls_size, stack_size;
GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr,
&tls_size);
top = bottom + stack_size;
uptr tls_begin, tls_end;
GetThreadStackAndTls(/*main=*/false, &bottom, &top, &tls_begin, &tls_end);
}

UnpoisonStack(bottom, top, "default");
Expand Down
9 changes: 3 additions & 6 deletions compiler-rt/lib/asan/asan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,10 @@ AsanThread *CreateMainThread() {
// OS-specific implementations that need more information passed through.
void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
DCHECK_EQ(options, nullptr);
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
&tls_begin_, &tls_size);
stack_top_ = RoundDownTo(stack_bottom_ + stack_size, ASAN_SHADOW_GRANULARITY);
GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_top_,
&tls_begin_, &tls_end_);
stack_top_ = RoundDownTo(stack_top_, ASAN_SHADOW_GRANULARITY);
stack_bottom_ = RoundDownTo(stack_bottom_, ASAN_SHADOW_GRANULARITY);
tls_end_ = tls_begin_ + tls_size;
dtls_ = DTLS_Get();

if (stack_top_ != stack_bottom_) {
Expand Down
9 changes: 2 additions & 7 deletions compiler-rt/lib/dfsan/dfsan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,8 @@ DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg,
}

void DFsanThread::SetThreadStackAndTls() {
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
&tls_size);
stack_.top = stack_.bottom + stack_size;
tls_end_ = tls_begin_ + tls_size;

GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_.top, &tls_begin_,
&tls_end_);
int local;
CHECK(AddrIsInStack((uptr)&local));
}
Expand Down
8 changes: 2 additions & 6 deletions compiler-rt/lib/hwasan/hwasan_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,8 @@ void HwasanOnDeadlySignal(int signo, void *info, void *context) {
}

void Thread::InitStackAndTls(const InitState *) {
uptr tls_size;
uptr stack_size;
GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, &tls_begin_,
&tls_size);
stack_top_ = stack_bottom_ + stack_size;
tls_end_ = tls_begin_ + tls_size;
GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_top_, &tls_begin_,
&tls_end_);
}

uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
Expand Down
8 changes: 2 additions & 6 deletions compiler-rt/lib/lsan/lsan_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ void ThreadContext::OnStarted(void *arg) {

void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) {
OnStartedArgs args;
uptr stack_size = 0;
uptr tls_size = 0;
GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size,
&args.tls_begin, &tls_size);
args.stack_end = args.stack_begin + stack_size;
args.tls_end = args.tls_begin + tls_size;
GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &args.stack_end,
&args.tls_begin, &args.tls_end);
GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
args.dtls = DTLS_Get();
ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args);
Expand Down
8 changes: 2 additions & 6 deletions compiler-rt/lib/memprof/memprof_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,8 @@ MemprofThread *CreateMainThread() {
// OS-specific implementations that need more information passed through.
void MemprofThread::SetThreadStackAndTls(const InitOptions *options) {
DCHECK_EQ(options, nullptr);
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
&tls_begin_, &tls_size);
stack_top_ = stack_bottom_ + stack_size;
tls_end_ = tls_begin_ + tls_size;
GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_top_,
&tls_begin_, &tls_end_);
dtls_ = DTLS_Get();

if (stack_top_ != stack_bottom_) {
Expand Down
9 changes: 2 additions & 7 deletions compiler-rt/lib/msan/msan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@ MsanThread *MsanThread::Create(thread_callback_t start_routine,
}

void MsanThread::SetThreadStackAndTls() {
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
&tls_size);
stack_.top = stack_.bottom + stack_size;
tls_end_ = tls_begin_ + tls_size;

GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_.top, &tls_begin_,
&tls_end_);
int local;
CHECK(AddrIsInStack((uptr)&local));
}
Expand Down
9 changes: 2 additions & 7 deletions compiler-rt/lib/nsan/nsan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,8 @@ NsanThread *NsanThread::Create(thread_callback_t start_routine, void *arg) {
}

void NsanThread::SetThreadStackAndTls() {
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
&tls_size);
stack_.top = stack_.bottom + stack_size;
tls_end_ = tls_begin_ + tls_size;

GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_.top, &tls_begin_,
&tls_end_);
int local;
CHECK(AddrIsInStack((uptr)&local));
}
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/sanitizer_common/sanitizer_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ int TgKill(pid_t pid, tid_t tid, int sig);
uptr GetThreadSelf();
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom);
void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr *tls_addr, uptr *tls_size);
void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
uptr *tls_begin, uptr *tls_end);

// Memory management
void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
Expand Down
28 changes: 18 additions & 10 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,25 +626,33 @@ uptr GetTlsSize() {
}
# endif

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr *tls_addr, uptr *tls_size) {
void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
uptr *tls_begin, uptr *tls_end) {
# if SANITIZER_GO
// Stub implementation for Go.
*stk_addr = *stk_size = *tls_addr = *tls_size = 0;
*stk_begin = 0;
*stk_end = 0;
*tls_begin = 0;
*tls_end = 0;
# else
GetTls(tls_addr, tls_size);
uptr tls_addr = 0;
uptr tls_size = 0;
GetTls(&tls_addr, &tls_size);
*tls_begin = tls_addr;
*tls_end = tls_addr + tls_size;

uptr stack_top, stack_bottom;
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
*stk_addr = stack_bottom;
*stk_size = stack_top - stack_bottom;
*stk_begin = stack_bottom;
*stk_end = stack_top;

if (!main) {
// If stack and tls intersect, make them non-intersecting.
if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
if (*stk_addr + *stk_size < *tls_addr + *tls_size)
*tls_size = *stk_addr + *stk_size - *tls_addr;
*stk_size = *tls_addr - *stk_addr;
CHECK_GE(*tls_begin, *stk_begin);
if (*tls_begin > *stk_begin && *tls_begin < *stk_end) {
if (*stk_end > *tls_end)
*tls_end = *stk_end;
*stk_end = *tls_begin;
}
}
# endif
Expand Down
27 changes: 12 additions & 15 deletions compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,21 +572,18 @@ uptr TlsSize() {
#endif
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr *tls_addr, uptr *tls_size) {
#if !SANITIZER_GO
uptr stack_top, stack_bottom;
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
*stk_addr = stack_bottom;
*stk_size = stack_top - stack_bottom;
*tls_addr = TlsBaseAddr();
*tls_size = TlsSize();
#else
*stk_addr = 0;
*stk_size = 0;
*tls_addr = 0;
*tls_size = 0;
#endif
void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
uptr *tls_begin, uptr *tls_end) {
# if !SANITIZER_GO
GetThreadStackTopAndBottom(main, stk_begin, stk_end);
*tls_begin = TlsBaseAddr();
*tls_end = *tls_begin + TlsSize();
# else
*stk_begin = 0;
*stk_end = 0;
*tls_begin = 0;
*tls_end = 0;
# endif
}

void ListOfModules::init() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
27 changes: 12 additions & 15 deletions compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,21 +876,18 @@ uptr GetTlsSize() {
void InitTlsSize() {
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr *tls_addr, uptr *tls_size) {
#if SANITIZER_GO
*stk_addr = 0;
*stk_size = 0;
*tls_addr = 0;
*tls_size = 0;
#else
uptr stack_top, stack_bottom;
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
*stk_addr = stack_bottom;
*stk_size = stack_top - stack_bottom;
*tls_addr = 0;
*tls_size = 0;
#endif
void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
uptr *tls_begin, uptr *tls_end) {
# if SANITIZER_GO
*stk_begin = 0;
*stk_end = 0;
*tls_begin = 0;
*tls_end = 0;
# else
GetThreadStackTopAndBottom(main, stk_begin, stk_end);
*tls_begin = 0;
*tls_end = 0;
# endif
}

void ReportFile::Write(const char *buffer, uptr length) {
Expand Down
33 changes: 16 additions & 17 deletions compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,30 +204,29 @@ TEST(SanitizerCommon, InternalMmapVectorSwap) {
}

void TestThreadInfo(bool main) {
uptr stk_addr = 0;
uptr stk_size = 0;
uptr tls_addr = 0;
uptr tls_size = 0;
GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
uptr stk_begin = 0;
uptr stk_end = 0;
uptr tls_begin = 0;
uptr tls_end = 0;
GetThreadStackAndTls(main, &stk_begin, &stk_end, &tls_begin, &tls_end);

int stack_var;
EXPECT_NE(stk_addr, (uptr)0);
EXPECT_NE(stk_size, (uptr)0);
EXPECT_GT((uptr)&stack_var, stk_addr);
EXPECT_LT((uptr)&stack_var, stk_addr + stk_size);
EXPECT_NE(stk_begin, (uptr)0);
EXPECT_GT(stk_end, stk_begin);
EXPECT_GT((uptr)&stack_var, stk_begin);
EXPECT_LT((uptr)&stack_var, stk_end);

#if SANITIZER_LINUX && defined(__x86_64__)
static __thread int thread_var;
EXPECT_NE(tls_addr, (uptr)0);
EXPECT_NE(tls_size, (uptr)0);
EXPECT_GT((uptr)&thread_var, tls_addr);
EXPECT_LT((uptr)&thread_var, tls_addr + tls_size);
EXPECT_NE(tls_begin, (uptr)0);
EXPECT_GT(tls_end, tls_begin);
EXPECT_GT((uptr)&thread_var, tls_begin);
EXPECT_LT((uptr)&thread_var, tls_end);

// Ensure that tls and stack do not intersect.
uptr tls_end = tls_addr + tls_size;
EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size);
EXPECT_TRUE(tls_end < stk_addr || tls_end >= stk_addr + stk_size);
EXPECT_TRUE((tls_addr < stk_addr) == (tls_end < stk_addr));
EXPECT_TRUE(tls_begin < stk_begin || tls_begin >= stk_end);
EXPECT_TRUE(tls_end < stk_begin || tls_end >= stk_end);
EXPECT_TRUE((tls_begin < stk_begin) == (tls_end < stk_begin));
#endif
}

Expand Down
10 changes: 6 additions & 4 deletions compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,16 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
#endif

uptr stk_addr = 0;
uptr stk_size = 0;
uptr stk_end = 0;
uptr tls_addr = 0;
uptr tls_size = 0;
uptr tls_end = 0;
#if !SANITIZER_GO
if (thread_type != ThreadType::Fiber)
GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,
&tls_size);
GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_end, &tls_addr,
&tls_end);
#endif
uptr stk_size = stk_end - stk_addr;
uptr tls_size = tls_end - tls_addr;
thr->stk_addr = stk_addr;
thr->stk_size = stk_size;
thr->tls_addr = tls_addr;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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

#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
Loading