[compiler-rt] r178754 - [msan] Unpoison siginfo_t and ucontext_t in signal handlers.
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Thu Apr 4 01:22:53 PDT 2013
Author: eugenis
Date: Thu Apr 4 03:22:52 2013
New Revision: 178754
URL: http://llvm.org/viewvc/llvm-project?rev=178754&view=rev
Log:
[msan] Unpoison siginfo_t and ucontext_t in signal handlers.
Add wrappers for all user signal handlers to unpoison the handler's arguments.
Modified:
compiler-rt/trunk/lib/msan/msan_interceptors.cc
compiler-rt/trunk/lib/msan/tests/msan_test.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=178754&r1=178753&r2=178754&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Thu Apr 4 03:22:52 2013
@@ -824,17 +824,64 @@ INTERCEPTOR(int, getrusage, int who, voi
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;
}
Modified: compiler-rt/trunk/lib/msan/tests/msan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/tests/msan_test.cc?rev=178754&r1=178753&r2=178754&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/tests/msan_test.cc (original)
+++ compiler-rt/trunk/lib/msan/tests/msan_test.cc Thu Apr 4 03:22:52 2013
@@ -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();
};
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc?rev=178754&r1=178753&r2=178754&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc Thu Apr 4 03:22:52 2013
@@ -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
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=178754&r1=178753&r2=178754&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Thu Apr 4 03:22:52 2013
@@ -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
More information about the llvm-commits
mailing list