Skip to content

Commit

Permalink
[msan] Save/restore va_arg_overflow_tls in signal handlers.
Browse files Browse the repository at this point in the history
llvm-svn: 189351
  • Loading branch information
eugenis committed Aug 27, 2013
1 parent 614a5ea commit cb22c67
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 29 deletions.
46 changes: 23 additions & 23 deletions compiler-rt/lib/msan/lit_tests/signal_stress_test.cc
@@ -1,4 +1,4 @@
// RUN: %clangxx_msan -O0 %s -o %t && %t
// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %t

// Test that va_arg shadow from a signal handler does not leak outside.

Expand All @@ -9,19 +9,14 @@
#include <sys/time.h>
#include <stdio.h>

const int kArgCnt = 20;
const int kSigCnt = 100;
const int kSigCnt = 200;

volatile int z;

void f(bool poisoned, ...) {
void f(bool poisoned, int n, ...) {
va_list vl;
va_start(vl, poisoned);
for (int i = 0; i < kArgCnt; ++i) {
va_start(vl, n);
for (int i = 0; i < n; ++i) {
void *p = va_arg(vl, void *);
if (poisoned)
assert(__msan_test_shadow(&p, sizeof(p)) == 0);
else
if (!poisoned)
assert(__msan_test_shadow(&p, sizeof(p)) == -1);
}
va_end(vl);
Expand All @@ -32,13 +27,10 @@ int sigcnt;
void SignalHandler(int signo) {
assert(signo == SIGPROF);
void *p;
void ** volatile q = &p;
f(true,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q);
void **volatile q = &p;
f(true, 10,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q);
++sigcnt;
}

Expand All @@ -52,12 +44,20 @@ int main() {
itv.it_value.tv_usec = 100;
setitimer(ITIMER_PROF, &itv, NULL);

void *p;
void **volatile q = &p;

do {
f(false,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0);
f(false, 20,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr);
f(true, 20,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q,
*q, *q, *q, *q, *q);
} while (sigcnt < kSigCnt);

itv.it_interval.tv_sec = 0;
Expand Down
22 changes: 20 additions & 2 deletions compiler-rt/lib/msan/msan.cc
Expand Up @@ -230,11 +230,29 @@ void UnpoisonParam(uptr n) {
internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls));
}

void UnpoisonThreadLocalState() {
// Backup MSan runtime TLS state.
// Implementation must be async-signal-safe.
// Instances of this class may live on the signal handler stack, and data size
// may be an issue.
void ScopedThreadLocalStateBackup::Backup() {
va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls;
}

void ScopedThreadLocalStateBackup::Restore() {
// A lame implementation that only keeps essential state and resets the rest.
__msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls;

internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls));
internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls));
internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls));
__msan_va_arg_overflow_size_tls = 0;

if (__msan_get_track_origins()) {
internal_memset(&__msan_retval_origin_tls, 0, sizeof(__msan_retval_tls));
internal_memset(__msan_param_origin_tls, 0, sizeof(__msan_param_origin_tls));
}
}

void UnpoisonThreadLocalState() {
}

} // namespace __msan
Expand Down
9 changes: 9 additions & 0 deletions compiler-rt/lib/msan/msan.h
Expand Up @@ -86,6 +86,15 @@ void UnpoisonThreadLocalState();
StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
common_flags()->fast_unwind_on_malloc)

class ScopedThreadLocalStateBackup {
public:
ScopedThreadLocalStateBackup() { Backup(); }
~ScopedThreadLocalStateBackup() { Restore(); }
void Backup();
void Restore();
private:
u64 va_arg_overflow_size_tls;
};
} // namespace __msan

#define MSAN_MALLOC_HOOK(ptr, size) \
Expand Down
10 changes: 6 additions & 4 deletions compiler-rt/lib/msan/msan_interceptors.cc
Expand Up @@ -911,17 +911,20 @@ static atomic_uintptr_t sigactions[kMaxSignals];
static StaticSpinMutex sigactions_mu;

static void SignalHandler(int signo) {
ScopedThreadLocalStateBackup stlsb;
stlsb.Backup();
UnpoisonParam(1);

typedef void (*signal_cb)(int x);
signal_cb cb =
(signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
cb(signo);

UnpoisonThreadLocalState();
stlsb.Restore();
}

static void SignalAction(int signo, void *si, void *uc) {
ScopedThreadLocalStateBackup stlsb;
stlsb.Backup();
UnpoisonParam(3);
__msan_unpoison(si, sizeof(__sanitizer_sigaction));
__msan_unpoison(uc, __sanitizer::ucontext_t_sz);
Expand All @@ -930,8 +933,7 @@ static void SignalAction(int signo, void *si, void *uc) {
sigaction_cb cb =
(sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
cb(signo, si, uc);

UnpoisonThreadLocalState();
stlsb.Restore();
}

INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
Expand Down

0 comments on commit cb22c67

Please sign in to comment.