[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