Index: compiler-rt/lib/msan/msan_interceptors.cc =================================================================== --- compiler-rt/lib/msan/msan_interceptors.cc +++ compiler-rt/lib/msan/msan_interceptors.cc @@ -997,67 +997,18 @@ 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)); -} +static void *signal_impl(int signum, void *handler); +static int sigaction_impl(int signum, const __sanitizer_sigaction *act, + __sanitizer_sigaction *oldact); -INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, - __sanitizer_sigaction *oldact) { - ENSURE_MSAN_INITED(); - if (act) read_sigaction(act); - int res; - if (flags()->wrap_signals) { - SpinMutexLock lock(&sigactions_mu); - CHECK_LT(signo, kMaxSignals); - uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); - __sanitizer_sigaction new_act; - __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr; - if (act) { - REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction)); - uptr cb = (uptr)pnew_act->sigaction; - uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo) - ? (uptr)SignalAction - : (uptr)SignalHandler; - if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { - atomic_store(&sigactions[signo], cb, memory_order_relaxed); - pnew_act->sigaction = (void (*)(int, void *, void *))new_cb; - } - } - res = REAL(sigaction)(signo, pnew_act, oldact); - if (res == 0 && oldact) { - uptr cb = (uptr)oldact->sigaction; - if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { - oldact->sigaction = (void (*)(int, void *, void *))old_cb; - } - } - } else { - res = REAL(sigaction)(signo, act, oldact); - } - - if (res == 0 && oldact) { - __msan_unpoison(oldact, sizeof(__sanitizer_sigaction)); - } - return res; +INTERCEPTOR(int, signal, int signum, void *handler) { + handler = signal_impl(signum, handler); + return REAL(signal)(signum, handler); } -INTERCEPTOR(int, signal, int signo, uptr cb) { - ENSURE_MSAN_INITED(); - if (flags()->wrap_signals) { - CHECK_LT(signo, kMaxSignals); - SpinMutexLock lock(&sigactions_mu); - if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { - atomic_store(&sigactions[signo], cb, memory_order_relaxed); - cb = (uptr) SignalHandler; - } - return REAL(signal)(signo, cb); - } else { - return REAL(signal)(signo, cb); - } +INTERCEPTOR(int, sigaction, int signum, const __sanitizer_sigaction *act, + __sanitizer_sigaction *oldact) { + return sigaction_impl(signum, act, oldact); } extern "C" int pthread_attr_init(void *attr); @@ -1315,6 +1266,68 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_common_interceptors.inc" +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)); +} + +static void *signal_impl(int signo, void *handler) { + ENSURE_MSAN_INITED(); + if (flags()->wrap_signals) { + CHECK_LT(signo, kMaxSignals); + SpinMutexLock lock(&sigactions_mu); + uptr cb = (uptr)handler; + if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { + atomic_store(&sigactions[signo], cb, memory_order_relaxed); + return (void *)&SignalHandler; + } + } + return handler; +} + +static int sigaction_impl(int signo, const __sanitizer_sigaction *act, + __sanitizer_sigaction *oldact) { + ENSURE_MSAN_INITED(); + if (act) read_sigaction(act); + int res; + if (flags()->wrap_signals) { + SpinMutexLock lock(&sigactions_mu); + CHECK_LT(signo, kMaxSignals); + uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); + __sanitizer_sigaction new_act; + __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr; + if (act) { + REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction)); + uptr cb = (uptr)pnew_act->sigaction; + uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo) + ? (uptr)SignalAction + : (uptr)SignalHandler; + if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { + atomic_store(&sigactions[signo], cb, memory_order_relaxed); + pnew_act->sigaction = (void (*)(int, void *, void *))new_cb; + } + } + res = REAL(sigaction)(signo, pnew_act, oldact); + if (res == 0 && oldact) { + uptr cb = (uptr)oldact->sigaction; + if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { + oldact->sigaction = (void (*)(int, void *, void *))old_cb; + } + } + } else { + res = REAL(sigaction)(signo, act, oldact); + } + + if (res == 0 && oldact) { + __msan_unpoison(oldact, sizeof(__sanitizer_sigaction)); + } + return res; +} + #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ do { \