139 lines · plain
1//===-- sanitizer_signal_interceptors.inc -----------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Signal interceptors for sanitizers.10//11//===----------------------------------------------------------------------===//12 13#include "interception/interception.h"14#include "sanitizer_common.h"15#include "sanitizer_internal_defs.h"16#include "sanitizer_platform_interceptors.h"17 18using namespace __sanitizer;19 20#if SANITIZER_NETBSD21#define sigaction_symname __sigaction1422#else23#define sigaction_symname sigaction24#endif25 26#ifndef SIGNAL_INTERCEPTOR_SIGNAL_IMPL27#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signum, handler) \28 { return REAL(func)(signum, handler); }29#endif30 31#ifndef SIGNAL_INTERCEPTOR_SIGACTION_IMPL32# define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \33 { \34 if (!REAL(sigaction_symname)) { \35 Printf( \36 "Warning: REAL(sigaction_symname) == nullptr. This may happen " \37 "if you link with ubsan statically. Sigaction will not work.\n"); \38 return -1; \39 } \40 return REAL(sigaction_symname)(signum, act, oldact); \41 }42#endif43 44#if SANITIZER_INTERCEPT_BSD_SIGNAL45INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {46 SIGNAL_INTERCEPTOR_ENTER();47 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;48 49 // TODO: support cloak_sanitizer_signal_handlers50 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);51}52#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)53#else // SANITIZER_INTERCEPT_BSD_SIGNAL54#define INIT_BSD_SIGNAL55#endif // SANITIZER_INTERCEPT_BSD_SIGNAL56 57#if SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION58INTERCEPTOR(uptr, signal, int signum, uptr handler) {59 SIGNAL_INTERCEPTOR_ENTER();60 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)61 // The user can neither view nor change the signal handler, regardless of62 // the cloak_sanitizer_signal_handlers setting. This differs from63 // sigaction().64 return (uptr) nullptr;65 66 uptr ret = +[](auto signal, int signum, uptr handler) {67 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);68 }(signal, signum, handler);69 70 if (ret != sig_err && SetSignalHandlerFromSanitizer(signum, false))71 // If the user sets a signal handler, it becomes uncloaked, even if they72 // reuse a sanitizer's signal handler.73 ret = sig_dfl;74 75 return ret;76}77#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)78 79INTERCEPTOR(int, sigaction_symname, int signum,80 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {81 SIGNAL_INTERCEPTOR_ENTER();82 83 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {84 if (!oldact) return 0;85 act = nullptr;86 // If cloak_sanitizer_signal_handlers=true, the user can neither view nor87 // change the signal handle.88 // If false, the user can view but not change the signal handler. This89 // differs from signal().90 }91 92 int ret = +[](int signum, const __sanitizer_sigaction* act,93 __sanitizer_sigaction* oldact) {94 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);95 }(signum, act, oldact);96 97 if (act) {98 if (ret == 0 && SetSignalHandlerFromSanitizer(signum, false)) {99 // If the user sets a signal handler, it becomes uncloaked, even if they100 // reuse a sanitizer's signal handler.101 102 if (oldact)103 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);104 }105 } else if (ret == 0 && oldact && IsSignalHandlerFromSanitizer(signum)) {106 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);107 }108 109 return ret;110}111#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)112 113namespace __sanitizer {114int real_sigaction(int signum, const void *act, void *oldact) {115 return REAL(sigaction_symname)(signum, (const __sanitizer_sigaction *)act,116 (__sanitizer_sigaction *)oldact);117}118} // namespace __sanitizer119#else // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION120#define INIT_SIGNAL121#define INIT_SIGACTION122// We need to have defined REAL(sigaction) on other systems.123namespace __sanitizer {124struct __sanitizer_sigaction;125}126DEFINE_REAL(int, sigaction, int signum, const __sanitizer_sigaction *act,127 __sanitizer_sigaction *oldact)128#endif // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION129 130static void InitializeSignalInterceptors() {131 static bool was_called_once;132 CHECK(!was_called_once);133 was_called_once = true;134 135 INIT_BSD_SIGNAL;136 INIT_SIGNAL;137 INIT_SIGACTION;138}139