diff options
| -rw-r--r-- | compiler-rt/lib/msan/lit_tests/signal_stress_test.cc | 71 | ||||
| -rw-r--r-- | compiler-rt/lib/msan/msan.cc | 7 | ||||
| -rw-r--r-- | compiler-rt/lib/msan/msan.h | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/msan/msan_interceptors.cc | 6 |
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, |

