summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-04-04 08:22:52 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-04-04 08:22:52 +0000
commit1f8b3538b49407943d5881329cdbb5c9181f68cc (patch)
tree49a8252b99b3a555a21e32613f9e2877c68b12a6
parentc01f4f0d4dc95e5b7f9eeb4f921b694181ff3427 (diff)
downloadbcm5719-llvm-1f8b3538b49407943d5881329cdbb5c9181f68cc.tar.gz
bcm5719-llvm-1f8b3538b49407943d5881329cdbb5c9181f68cc.zip
[msan] Unpoison siginfo_t and ucontext_t in signal handlers.
Add wrappers for all user signal handlers to unpoison the handler's arguments. llvm-svn: 178754
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cc54
-rw-r--r--compiler-rt/lib/msan/tests/msan_test.cc49
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc23
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h13
4 files changed, 135 insertions, 4 deletions
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index 17b4bf8c103..00c54f2a5e9 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -824,17 +824,64 @@ INTERCEPTOR(int, getrusage, int who, void *usage) {
return res;
}
-INTERCEPTOR(int, sigaction, int signum, const void *act, void *oldact) {
+const int kMaxSignals = 1024;
+static uptr sigactions[kMaxSignals];
+static StaticSpinMutex sigactions_mu;
+
+static void SignalHandler(int signo) {
+ typedef void (*signal_cb)(int);
+ signal_cb cb = (signal_cb)sigactions[signo];
+ cb(signo);
+}
+
+static void SignalAction(int signo, void *si, void *uc) {
+ __msan_unpoison(si, __sanitizer::struct_sigaction_sz);
+ __msan_unpoison(uc, __sanitizer::struct_ucontext_sz);
+
+ typedef void (*sigaction_cb)(int, void *, void *);
+ sigaction_cb cb = (sigaction_cb)sigactions[signo];
+ cb(signo, si, uc);
+}
+
+INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *oldact) {
ENSURE_MSAN_INITED();
// FIXME: check that *act is unpoisoned.
// That requires intercepting all of sigemptyset, sigfillset, etc.
- int res = REAL(sigaction)(signum, act, oldact);
- if (res == 0) {
+ SpinMutexLock lock(&sigactions_mu);
+ CHECK_LT(signo, kMaxSignals);
+ uptr old_cb = sigactions[signo];
+ __sanitizer_sigaction new_act;
+ __sanitizer_sigaction *pnew_act = act ? &new_act : 0;
+ if (act) {
+ internal_memcpy(pnew_act, act, __sanitizer::struct_sigaction_sz);
+ uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(pnew_act);
+ uptr new_cb = __sanitizer::__sanitizer_get_sigaction_sa_siginfo(pnew_act) ?
+ (uptr)SignalAction : (uptr)SignalHandler;
+ if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
+ sigactions[signo] = cb;
+ __sanitizer::__sanitizer_set_sigaction_sa_sigaction(pnew_act, new_cb);
+ }
+ }
+ int res = REAL(sigaction)(signo, pnew_act, oldact);
+ if (res == 0 && oldact) {
__msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
+ __sanitizer::__sanitizer_set_sigaction_sa_sigaction(oldact, old_cb);
}
return res;
}
+INTERCEPTOR(int, signal, int signo, uptr cb) {
+ ENSURE_MSAN_INITED();
+ CHECK_LT(signo, kMaxSignals);
+ SpinMutexLock lock(&sigactions_mu);
+ if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
+ sigactions[signo] = cb;
+ cb = (uptr)SignalHandler;
+ }
+ return REAL(signal)(signo, cb);
+}
+
extern "C" int pthread_attr_init(void *attr);
extern "C" int pthread_attr_destroy(void *attr);
extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
@@ -1069,6 +1116,7 @@ void InitializeInterceptors() {
INTERCEPT_FUNCTION(dlopen);
INTERCEPT_FUNCTION(getrusage);
INTERCEPT_FUNCTION(sigaction);
+ INTERCEPT_FUNCTION(signal);
INTERCEPT_FUNCTION(pthread_create);
inited = 1;
}
diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc
index 3ae9a286c34..e6612baa0f7 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cc
+++ b/compiler-rt/lib/msan/tests/msan_test.cc
@@ -960,6 +960,55 @@ TEST(MemorySanitizer, frexp) {
EXPECT_NOT_POISONED(x);
}
+namespace {
+
+static int cnt;
+
+void SigactionHandler(int signo, siginfo_t* si, void* uc) {
+ assert(signo == SIGPROF);
+ assert(si);
+ EXPECT_NOT_POISONED(si->si_errno);
+ EXPECT_NOT_POISONED(si->si_pid);
+#if __linux__
+# if defined(__x86_64__)
+ EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_RIP]);
+# elif defined(__i386__)
+ EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_EIP]);
+# endif
+#endif
+ ++cnt;
+}
+
+TEST(MemorySanitizer, sigaction) {
+ struct sigaction act = {};
+ act.sa_flags |= SA_SIGINFO;
+ act.sa_sigaction = &SigactionHandler;
+ sigaction(SIGPROF, &act, 0);
+
+ kill(getpid(), SIGPROF);
+
+ act.sa_flags &= ~SA_SIGINFO;
+ act.sa_handler = SIG_DFL;
+ sigaction(SIGPROF, &act, 0);
+
+ act.sa_flags &= ~SA_SIGINFO;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPROF, &act, 0);
+ kill(getpid(), SIGPROF);
+
+ act.sa_flags |= SA_SIGINFO;
+ act.sa_sigaction = &SigactionHandler;
+ sigaction(SIGPROF, &act, 0);
+ kill(getpid(), SIGPROF);
+
+ act.sa_flags &= ~SA_SIGINFO;
+ act.sa_handler = SIG_DFL;
+ sigaction(SIGPROF, &act, 0);
+ EXPECT_EQ(2, cnt);
+}
+
+} // namespace
+
struct StructWithDtor {
~StructWithDtor();
};
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index c640e947767..fd39cb2848e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -29,6 +29,7 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>
+#include <sys/ucontext.h>
#include <time.h>
#if SANITIZER_LINUX
@@ -44,6 +45,7 @@ namespace __sanitizer {
unsigned struct_tm_sz = sizeof(struct tm);
unsigned struct_passwd_sz = sizeof(struct passwd);
unsigned struct_sigaction_sz = sizeof(struct sigaction);
+ unsigned struct_ucontext_sz = sizeof(struct ucontext);
unsigned struct_itimerval_sz = sizeof(struct itimerval);
unsigned pthread_t_sz = sizeof(pthread_t);
@@ -61,6 +63,9 @@ namespace __sanitizer {
unsigned struct_statfs64_sz = sizeof(struct statfs64);
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+ uptr sig_ign = (uptr)SIG_IGN;
+ uptr sig_dfl = (uptr)SIG_DFL;
+
void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx) {
return ((struct msghdr *)msg)->msg_iov[idx].iov_base;
}
@@ -76,8 +81,24 @@ namespace __sanitizer {
uptr __sanitizer_get_socklen_t(void* socklen_ptr) {
return *(socklen_t*)socklen_ptr;
}
+
+ uptr __sanitizer_get_sigaction_sa_sigaction(void *act) {
+ struct sigaction *a = (struct sigaction *)act;
+ // Check that sa_sigaction and sa_handler are the same.
+ CHECK((void *)&(a->sa_sigaction) == (void *)&(a->sa_handler));
+ return (uptr) a->sa_sigaction;
+ }
+ void __sanitizer_set_sigaction_sa_sigaction(void *act, uptr cb) {
+ struct sigaction *a = (struct sigaction *)act;
+ a->sa_sigaction = (void (*)(int, siginfo_t *, void *))cb;
+ }
+ bool __sanitizer_get_sigaction_sa_siginfo(void *act) {
+ struct sigaction *a = (struct sigaction *)act;
+ return a->sa_flags & SA_SIGINFO;
+ }
} // namespace __sanitizer
COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
-
+COMPILER_CHECK(sizeof(__sanitizer::struct_sigaction_max_sz) >=
+ sizeof(__sanitizer::struct_sigaction_sz));
#endif // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 18b41065e82..bdec8e5c21c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -25,6 +25,7 @@ namespace __sanitizer {
extern unsigned struct_tm_sz;
extern unsigned struct_passwd_sz;
extern unsigned struct_sigaction_sz;
+ extern unsigned struct_ucontext_sz;
extern unsigned struct_itimerval_sz;
extern unsigned pthread_t_sz;
@@ -54,6 +55,18 @@ namespace __sanitizer {
char size[pthread_attr_t_max_sz]; // NOLINT
void *align;
};
+
+ uptr __sanitizer_get_sigaction_sa_sigaction(void *act);
+ void __sanitizer_set_sigaction_sa_sigaction(void *act, uptr cb);
+ bool __sanitizer_get_sigaction_sa_siginfo(void *act);
+
+ const unsigned struct_sigaction_max_sz = 256;
+ union __sanitizer_sigaction {
+ char size[struct_sigaction_max_sz]; // NOLINT
+ };
+
+ extern uptr sig_ign;
+ extern uptr sig_dfl;
} // namespace __sanitizer
#endif
OpenPOWER on IntegriCloud