Index: compiler-rt/lib/msan/msan_interceptors.cc =================================================================== --- compiler-rt/lib/msan/msan_interceptors.cc +++ compiler-rt/lib/msan/msan_interceptors.cc @@ -983,11 +983,21 @@ 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->handler, sizeof(act->handler)); + else + CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction)); + 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); Index: compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3589,7 +3589,7 @@ 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, 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, 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 @@ 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 @@ __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. Index: compiler-rt/test/msan/Linux/poll.cc =================================================================== --- /dev/null +++ compiler-rt/test/msan/Linux/poll.cc @@ -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 +#include +#include +#include + +#include + +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; +} Index: compiler-rt/test/msan/sigaction.cc =================================================================== --- /dev/null +++ compiler-rt/test/msan/sigaction.cc @@ -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 +#include +#include +#include +#include + +#include + +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; +} Index: compiler-rt/test/msan/sigwait.cc =================================================================== --- compiler-rt/test/msan/sigwait.cc +++ compiler-rt/test/msan/sigwait.cc @@ -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 -#include #include #include #include +#include + 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);