summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-08-27 12:59:39 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-08-27 12:59:39 +0000
commitc41798152f3abde45f0107ebe5b867f909ec11eb (patch)
tree592826f4fed0362f1b978e52b10eb3c0465004b6
parentbb25af5f7b1042cd5114de9285bc26f54d8af555 (diff)
downloadbcm5719-llvm-c41798152f3abde45f0107ebe5b867f909ec11eb.tar.gz
bcm5719-llvm-c41798152f3abde45f0107ebe5b867f909ec11eb.zip
[msan] Unpoison all TLS shadow when leaving a signal handler.
llvm-svn: 189343
-rw-r--r--compiler-rt/lib/msan/lit_tests/signal_stress_test.cc71
-rw-r--r--compiler-rt/lib/msan/msan.cc7
-rw-r--r--compiler-rt/lib/msan/msan.h1
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cc6
4 files changed, 85 insertions, 0 deletions
diff --git a/compiler-rt/lib/msan/lit_tests/signal_stress_test.cc b/compiler-rt/lib/msan/lit_tests/signal_stress_test.cc
new file mode 100644
index 00000000000..e632cde35fa
--- /dev/null
+++ b/compiler-rt/lib/msan/lit_tests/signal_stress_test.cc
@@ -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;
+}
diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc
index 24912b7b835..d7912fa8c6a 100644
--- a/compiler-rt/lib/msan/msan.cc
+++ b/compiler-rt/lib/msan/msan.cc
@@ -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.
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index b4bf6425302..e95ac9e6c8a 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -76,6 +76,7 @@ void ReportAtExitStatistics();
// Unpoison first n function arguments.
void UnpoisonParam(uptr n);
+void UnpoisonThreadLocalState();
#define GET_MALLOC_STACK_TRACE \
StackTrace stack; \
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index 5e89ef54c3a..eb6888a3a8b 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -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,
OpenPOWER on IntegriCloud