diff options
-rw-r--r-- | lib/msan/msan_interceptors.cc | 10 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common_interceptors.inc | 10 | ||||
-rw-r--r-- | test/msan/Linux/poll.cc | 42 | ||||
-rw-r--r-- | test/msan/sigaction.cc | 47 | ||||
-rw-r--r-- | test/msan/sigwait.cc | 7 |
5 files changed, 110 insertions, 6 deletions
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 08eb261aa..916e25557 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -983,11 +983,21 @@ static void SignalAction(int signo, void *si, void *uc) { 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); diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index e6f0f1129..b9c182e65 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3589,7 +3589,7 @@ INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds, 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, __sanitizer_wordexp_t *p, int flags) { 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_sigset_t *set, int *sig) { 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, __sanitizer_sigset_t *set, void *info, 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 *set, __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. diff --git a/test/msan/Linux/poll.cc b/test/msan/Linux/poll.cc new file mode 100644 index 000000000..7870d18e0 --- /dev/null +++ b/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 <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; +} diff --git a/test/msan/sigaction.cc b/test/msan/sigaction.cc new file mode 100644 index 000000000..0c69f115f --- /dev/null +++ b/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 <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; +} diff --git a/test/msan/sigwait.cc b/test/msan/sigwait.cc index f2e77cfd6..222fc34a1 100644 --- a/test/msan/sigwait.cc +++ b/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 <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); |