[msan] Unpoison all TLS shadow when leaving a signal handler.

llvm-svn: 189343
This commit is contained in:
Evgeniy Stepanov 2013-08-27 12:59:39 +00:00
parent bb25af5f7b
commit c41798152f
4 changed files with 85 additions and 0 deletions

View File

@ -0,0 +1,71 @@
// RUN: %clangxx_msan -O0 %s -o %t && %t
// Test that va_arg shadow from a signal handler does not leak outside.
#include <signal.h>
#include <stdarg.h>
#include <sanitizer/msan_interface.h>
#include <assert.h>
#include <sys/time.h>
#include <stdio.h>
const int kArgCnt = 20;
const int kSigCnt = 100;
volatile int z;
void f(bool poisoned, ...) {
va_list vl;
va_start(vl, poisoned);
for (int i = 0; i < kArgCnt; ++i) {
void *p = va_arg(vl, void *);
if (poisoned)
assert(__msan_test_shadow(&p, sizeof(p)) == 0);
else
assert(__msan_test_shadow(&p, sizeof(p)) == -1);
}
va_end(vl);
}
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);
++sigcnt;
}
int main() {
signal(SIGPROF, SignalHandler);
itimerval itv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 100;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 100;
setitimer(ITIMER_PROF, &itv, NULL);
do {
f(false,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0);
} while (sigcnt < kSigCnt);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_PROF, &itv, NULL);
signal(SIGPROF, SIG_DFL);
return 0;
}

View File

@ -230,6 +230,13 @@ void UnpoisonParam(uptr n) {
internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls));
}
void UnpoisonThreadLocalState() {
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;
}
} // namespace __msan
// Interface.

View File

@ -76,6 +76,7 @@ void ReportAtExitStatistics();
// Unpoison first n function arguments.
void UnpoisonParam(uptr n);
void UnpoisonThreadLocalState();
#define GET_MALLOC_STACK_TRACE \
StackTrace stack; \

View File

@ -911,10 +911,14 @@ static atomic_uintptr_t sigactions[kMaxSignals];
static StaticSpinMutex sigactions_mu;
static void SignalHandler(int signo) {
UnpoisonParam(1);
typedef void (*signal_cb)(int x);
signal_cb cb =
(signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
cb(signo);
UnpoisonThreadLocalState();
}
static void SignalAction(int signo, void *si, void *uc) {
@ -926,6 +930,8 @@ 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();
}
INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,