Index: compiler-rt/lib/msan/msan_interceptors.cc =================================================================== --- compiler-rt/lib/msan/msan_interceptors.cc +++ compiler-rt/lib/msan/msan_interceptors.cc @@ -109,7 +109,7 @@ #define CHECK_UNPOISONED(x, n) \ do { \ if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \ - } while (0); + } while (0) #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \ CHECK_UNPOISONED((x), \ @@ -134,7 +134,7 @@ INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) { ENSURE_MSAN_INITED(); - CHECK_UNPOISONED_STRING(path, 0) + CHECK_UNPOISONED_STRING(path, 0); SSIZE_T res = REAL(readlink)(path, buf, bufsiz); if (res > 0) __msan_unpoison(buf, res); @@ -601,7 +601,7 @@ INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) { ENSURE_MSAN_INITED(); - CHECK_UNPOISONED_STRING(name, 0) + CHECK_UNPOISONED_STRING(name, 0); int res = REAL(setenv)(name, value, overwrite); if (!res) UnpoisonEnviron(); return res; @@ -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,40 @@ +// RUN: %clangxx_msan -O0 -std=c++11 -g %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CLEAN +// RUN: %clangxx_msan -DTEST_A -O0 -std=c++11 -g %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=A +// RUN: %clangxx_msan -DTEST_B -O0 -std=c++11 -g %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=B + +#include +#include +#include +#include + +#include + +int main(void) { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 1000; + int res = ppoll(nullptr, 0, &ts, nullptr); + assert(res == 0); + +#ifdef TEST_A + __msan_poison(&ts.tv_sec, sizeof(ts.tv_sec)); + ppoll(nullptr, 0, &ts, nullptr); + // A: use-of-uninitialized-value +#endif + + // A-NOT: ==1 + // B: ==1 + fprintf(stderr, "==1\n"); + + sigset_t sig; +#ifndef TEST_B + sigemptyset(&sig); +#endif + 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,65 @@ +// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t +// RUN: %clangxx_msan -DTEST_A -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_msan -DTEST_B -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_msan -DTEST_C -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); + _exit(0); + } else { + int sig; + int res = sigwait(&s, &sig); + assert(!res); + // The following checks that sig is initialized. + assert(sig == SIGUSR1); + } +} + +void handler(int) {} +void action(int, siginfo_t *, void *) {} + +int main(void) { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); +#ifdef HANDLER + sa.sa_handler = handler; +#else + sa.sa_sigaction = action; + sa.sa_flags = SA_SIGINFO; +#endif + +#ifdef TEST_A +#ifdef HANDLER + __msan_poison(&sa.sa_handler, sizeof(sa.sa_handler)); +#else + __msan_poison(&sa.sa_sigaction, sizeof(sa.sa_sigaction)); +#endif +#endif +#ifdef TEST_B + __msan_poison(&sa.sa_flags, sizeof(sa.sa_flags)); +#endif +#ifdef TEST_C + __msan_poison(&sa.sa_mask, sizeof(sa.sa_mask)); +#endif + // 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);