[compiler-rt] r312576 - [msan] Check sigset_t and sigaction arguments.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 5 14:08:56 PDT 2017


Author: eugenis
Date: Tue Sep  5 14:08:56 2017
New Revision: 312576

URL: http://llvm.org/viewvc/llvm-project?rev=312576&view=rev
Log:
[msan] Check sigset_t and sigaction arguments.

Summary:
Check sigset_t arguments in ppoll, sig*wait*, sigprocmask
interceptors, and the entire "struct sigaction" in sigaction. This
can be done because sigemptyset/sigfullset are intercepted and
signal masks should be correctly marked as initialized.

Reviewers: vitalybuka

Subscribers: kubamracek, llvm-commits

Differential Revision: https://reviews.llvm.org/D37367

Added:
    compiler-rt/trunk/test/msan/Linux/poll.cc
    compiler-rt/trunk/test/msan/sigaction.cc
Modified:
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/test/msan/sigwait.cc

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=312576&r1=312575&r2=312576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Tue Sep  5 14:08:56 2017
@@ -983,11 +983,21 @@ static void SignalAction(int signo, void
   cb(signo, si, uc);
 }
 
+static void read_sigaction(const __sanitizer_sigaction *act) {
+  CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
+  if (act->sa_flags & __sanitizer::sa_siginfo)
+    CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
+  else
+    CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
+  CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
+}
+
 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.
+  if (act) read_sigaction(act);
   int res;
   if (flags()->wrap_signals) {
     SpinMutexLock lock(&sigactions_mu);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=312576&r1=312575&r2=312576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Tue Sep  5 14:08:56 2017
@@ -3589,7 +3589,7 @@ INTERCEPTOR(int, ppoll, __sanitizer_poll
   if (fds && nfds) read_pollfd(ctx, fds, nfds);
   if (timeout_ts)
     COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
-  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
+  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
   int res =
       COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
   if (fds && nfds) write_pollfd(ctx, fds, nfds);
@@ -3630,7 +3630,7 @@ INTERCEPTOR(int, wordexp, char *s, __san
 INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
-  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
@@ -3647,7 +3647,7 @@ INTERCEPTOR(int, sigwait, __sanitizer_si
 INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
-  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
@@ -3666,7 +3666,7 @@ INTERCEPTOR(int, sigtimedwait, __sanitiz
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
   if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
-  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
@@ -3729,7 +3729,7 @@ INTERCEPTOR(int, sigprocmask, int how, _
             __sanitizer_sigset_t *oldset) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
-  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
   // FIXME: under ASan the call below may write to freed memory and corrupt
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.

Added: compiler-rt/trunk/test/msan/Linux/poll.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/Linux/poll.cc?rev=312576&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/Linux/poll.cc (added)
+++ compiler-rt/trunk/test/msan/Linux/poll.cc Tue Sep  5 14:08:56 2017
@@ -0,0 +1,42 @@
+// RUN: %clangxx_msan -O0 -std=c++11 -g %s -o %t
+// RUN: %run %t _ 2>&1 | FileCheck %s --check-prefix=CLEAN
+// RUN: not %run %t A 2>&1 | FileCheck %s --check-prefix=A
+// RUN: not %run %t B 2>&1 | FileCheck %s --check-prefix=B
+
+#include <assert.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <sanitizer/msan_interface.h>
+
+int main(int argc, char **argv) {
+  char T = argv[1][0];
+
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 1000;
+  int res = ppoll(nullptr, 0, &ts, nullptr);
+  assert(res == 0);
+
+  if (T == 'A') {
+    __msan_poison(&ts.tv_sec, sizeof(ts.tv_sec));
+    ppoll(nullptr, 0, &ts, nullptr);
+    // A: use-of-uninitialized-value
+  }
+
+  // A-NOT: ==1
+  // B: ==1
+  fprintf(stderr, "==1\n");
+
+  sigset_t sig;
+  if (T != 'B')
+    sigemptyset(&sig);
+  ppoll(nullptr, 0, &ts, &sig);
+  // B: use-of-uninitialized-value
+
+  // B-NOT: ==2
+  // CLEAN: ==2
+  fprintf(stderr, "==2\n");
+  return 0;
+}

Added: compiler-rt/trunk/test/msan/sigaction.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/sigaction.cc?rev=312576&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/sigaction.cc (added)
+++ compiler-rt/trunk/test/msan/sigaction.cc Tue Sep  5 14:08:56 2017
@@ -0,0 +1,47 @@
+// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t
+// RUN: %run %t __
+// RUN: not %run %t A_ 2>&1 | FileCheck %s
+// RUN: not %run %t AH 2>&1 | FileCheck %s
+// RUN: not %run %t B_ 2>&1 | FileCheck %s
+// RUN: not %run %t BH 2>&1 | FileCheck %s
+// RUN: not %run %t C_ 2>&1 | FileCheck %s
+// RUN: not %run %t CH 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <sanitizer/msan_interface.h>
+
+void handler(int) {}
+void action(int, siginfo_t *, void *) {}
+
+int main(int argc, char **argv) {
+  char T = argv[1][0];
+  char H = argv[1][1];
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  if (H == 'H') {
+    sa.sa_handler = handler;
+  } else {
+    sa.sa_sigaction = action;
+    sa.sa_flags = SA_SIGINFO;
+  }
+
+  if (T == 'A') {
+    if (H == 'H')
+      __msan_poison(&sa.sa_handler, sizeof(sa.sa_handler));
+    else
+      __msan_poison(&sa.sa_sigaction, sizeof(sa.sa_sigaction));
+  }
+  if (T == 'B')
+    __msan_poison(&sa.sa_flags, sizeof(sa.sa_flags));
+  if (T == 'C')
+    __msan_poison(&sa.sa_mask, sizeof(sa.sa_mask));
+  // CHECK: use-of-uninitialized-value
+  int res = sigaction(SIGUSR1, &sa, nullptr);
+  assert(res == 0);
+  return 0;
+}

Modified: compiler-rt/trunk/test/msan/sigwait.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/sigwait.cc?rev=312576&r1=312575&r2=312576&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/sigwait.cc (original)
+++ compiler-rt/trunk/test/msan/sigwait.cc Tue Sep  5 14:08:56 2017
@@ -1,16 +1,21 @@
 // RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DPOSITIVE -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
-#include <sanitizer/msan_interface.h>
 #include <signal.h>
 #include <sys/time.h>
 #include <unistd.h>
 
+#include <sanitizer/msan_interface.h>
+
 void test_sigwait() {
   sigset_t s;
+#ifndef POSITIVE
   sigemptyset(&s);
   sigaddset(&s, SIGUSR1);
+#endif
   sigprocmask(SIG_BLOCK, &s, 0);
+  // CHECK:  MemorySanitizer: use-of-uninitialized-value
 
   if (pid_t pid = fork()) {
     kill(pid, SIGUSR1);




More information about the llvm-commits mailing list