tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

failure_signal_handler.cc (14071B)


      1 //
      2 // Copyright 2018 The Abseil Authors.
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      https://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "absl/debugging/failure_signal_handler.h"
     18 
     19 #include "absl/base/config.h"
     20 
     21 #ifdef _WIN32
     22 #include <windows.h>
     23 #else
     24 #include <pthread.h>
     25 #include <sched.h>
     26 #include <unistd.h>
     27 #endif
     28 
     29 #ifdef __APPLE__
     30 #include <TargetConditionals.h>
     31 #endif
     32 
     33 #ifdef ABSL_HAVE_MMAP
     34 #include <sys/mman.h>
     35 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
     36 #define MAP_ANONYMOUS MAP_ANON
     37 #endif
     38 #endif
     39 
     40 #ifdef __linux__
     41 #include <sys/prctl.h>
     42 #endif
     43 
     44 #include <algorithm>
     45 #include <atomic>
     46 #include <cerrno>
     47 #include <csignal>
     48 #include <cstdio>
     49 #include <cstring>
     50 #include <ctime>
     51 
     52 #include "absl/base/attributes.h"
     53 #include "absl/base/internal/raw_logging.h"
     54 #include "absl/base/internal/sysinfo.h"
     55 #include "absl/debugging/internal/examine_stack.h"
     56 #include "absl/debugging/stacktrace.h"
     57 
     58 #if !defined(_WIN32) && !defined(__wasi__)
     59 #define ABSL_HAVE_SIGACTION
     60 // Apple WatchOS and TVOS don't allow sigaltstack
     61 // Apple macOS has sigaltstack, but using it makes backtrace() unusable.
     62 #if !(defined(TARGET_OS_OSX) && TARGET_OS_OSX) &&     \
     63    !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
     64    !(defined(TARGET_OS_TV) && TARGET_OS_TV) && !defined(__QNX__)
     65 #define ABSL_HAVE_SIGALTSTACK
     66 #endif
     67 #endif
     68 
     69 // ABSL_HAVE_PTHREAD_CPU_NUMBER_NP
     70 //
     71 // Checks whether pthread_cpu_number_np is available.
     72 #ifdef ABSL_HAVE_PTHREAD_CPU_NUMBER_NP
     73 #error ABSL_HAVE_PTHREAD_CPU_NUMBER_NP cannot be directly set
     74 #elif defined(__APPLE__) && defined(__has_include) &&              \
     75    ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&    \
     76      __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) ||  \
     77     (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) &&   \
     78      __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140200) || \
     79     (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) &&    \
     80      __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70100) ||   \
     81     (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) &&       \
     82      __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140200))
     83 #define ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 1
     84 #endif
     85 
     86 namespace absl {
     87 ABSL_NAMESPACE_BEGIN
     88 
     89 ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;
     90 
     91 // Resets the signal handler for signo to the default action for that
     92 // signal, then raises the signal.
     93 static void RaiseToDefaultHandler(int signo) {
     94  signal(signo, SIG_DFL);
     95  raise(signo);
     96 }
     97 
     98 struct FailureSignalData {
     99  const int signo;
    100  const char* const as_string;
    101 #ifdef ABSL_HAVE_SIGACTION
    102  struct sigaction previous_action;
    103  // StructSigaction is used to silence -Wmissing-field-initializers.
    104  using StructSigaction = struct sigaction;
    105 #define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
    106 #else
    107  void (*previous_handler)(int);
    108 #define FSD_PREVIOUS_INIT SIG_DFL
    109 #endif
    110 };
    111 
    112 ABSL_CONST_INIT static FailureSignalData failure_signal_data[] = {
    113    {SIGSEGV, "SIGSEGV", FSD_PREVIOUS_INIT},
    114    {SIGILL, "SIGILL", FSD_PREVIOUS_INIT},
    115    {SIGFPE, "SIGFPE", FSD_PREVIOUS_INIT},
    116    {SIGABRT, "SIGABRT", FSD_PREVIOUS_INIT},
    117    {SIGTERM, "SIGTERM", FSD_PREVIOUS_INIT},
    118 #ifndef _WIN32
    119    {SIGBUS, "SIGBUS", FSD_PREVIOUS_INIT},
    120    {SIGTRAP, "SIGTRAP", FSD_PREVIOUS_INIT},
    121 #endif
    122 };
    123 
    124 #undef FSD_PREVIOUS_INIT
    125 
    126 static void RaiseToPreviousHandler(int signo) {
    127  // Search for the previous handler.
    128  for (const auto& it : failure_signal_data) {
    129    if (it.signo == signo) {
    130 #ifdef ABSL_HAVE_SIGACTION
    131      sigaction(signo, &it.previous_action, nullptr);
    132 #else
    133      signal(signo, it.previous_handler);
    134 #endif
    135      raise(signo);
    136      return;
    137    }
    138  }
    139 
    140  // Not found, use the default handler.
    141  RaiseToDefaultHandler(signo);
    142 }
    143 
    144 namespace debugging_internal {
    145 
    146 const char* FailureSignalToString(int signo) {
    147  for (const auto& it : failure_signal_data) {
    148    if (it.signo == signo) {
    149      return it.as_string;
    150    }
    151  }
    152  return "";
    153 }
    154 
    155 }  // namespace debugging_internal
    156 
    157 #ifdef ABSL_HAVE_SIGALTSTACK
    158 
    159 static bool SetupAlternateStackOnce() {
    160 #if defined(__wasm__) || defined(__asjms__)
    161  const size_t page_mask = getpagesize() - 1;
    162 #else
    163  const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1;
    164 #endif
    165  size_t stack_size =
    166      (std::max(static_cast<size_t>(SIGSTKSZ), size_t{65536}) + page_mask) &
    167      ~page_mask;
    168 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
    169    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
    170  // Account for sanitizer instrumentation requiring additional stack space.
    171  stack_size *= 5;
    172 #endif
    173 
    174  stack_t sigstk;
    175  memset(&sigstk, 0, sizeof(sigstk));
    176  sigstk.ss_size = stack_size;
    177 
    178 #ifdef ABSL_HAVE_MMAP
    179 #ifndef MAP_STACK
    180 #define MAP_STACK 0
    181 #endif
    182  sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,
    183                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
    184  if (sigstk.ss_sp == MAP_FAILED) {
    185    ABSL_RAW_LOG(FATAL, "mmap() for alternate signal stack failed");
    186  }
    187 #else
    188  sigstk.ss_sp = malloc(sigstk.ss_size);
    189  if (sigstk.ss_sp == nullptr) {
    190    ABSL_RAW_LOG(FATAL, "malloc() for alternate signal stack failed");
    191  }
    192 #endif
    193 
    194  if (sigaltstack(&sigstk, nullptr) != 0) {
    195    ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno);
    196  }
    197 
    198 #ifdef __linux__
    199 #if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
    200  // Make a best-effort attempt to name the allocated region in
    201  // /proc/$PID/smaps.
    202  //
    203  // The call to prctl() may fail if the kernel was not configured with the
    204  // CONFIG_ANON_VMA_NAME kernel option.  This is OK since the call is
    205  // primarily a debugging aid.
    206  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, sigstk.ss_sp, sigstk.ss_size,
    207        "absl-signalstack");
    208 #endif
    209 #endif  // __linux__
    210 
    211  return true;
    212 }
    213 
    214 #endif
    215 
    216 #ifdef ABSL_HAVE_SIGACTION
    217 
    218 // Sets up an alternate stack for signal handlers once.
    219 // Returns the appropriate flag for sig_action.sa_flags
    220 // if the system supports using an alternate stack.
    221 static int MaybeSetupAlternateStack() {
    222 #ifdef ABSL_HAVE_SIGALTSTACK
    223  ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();
    224  return SA_ONSTACK;
    225 #else
    226  return 0;
    227 #endif
    228 }
    229 
    230 static void InstallOneFailureHandler(FailureSignalData* data,
    231                                     void (*handler)(int, siginfo_t*, void*)) {
    232  struct sigaction act;
    233  memset(&act, 0, sizeof(act));
    234  sigemptyset(&act.sa_mask);
    235  act.sa_flags |= SA_SIGINFO;
    236  // SA_NODEFER is required to handle SIGABRT from
    237  // ImmediateAbortSignalHandler().
    238  act.sa_flags |= SA_NODEFER;
    239  if (fsh_options.use_alternate_stack) {
    240    act.sa_flags |= MaybeSetupAlternateStack();
    241  }
    242  act.sa_sigaction = handler;
    243  ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0,
    244                 "sigaction() failed");
    245 }
    246 
    247 #else
    248 
    249 static void InstallOneFailureHandler(FailureSignalData* data,
    250                                     void (*handler)(int)) {
    251  data->previous_handler = signal(data->signo, handler);
    252  ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, "signal() failed");
    253 }
    254 
    255 #endif
    256 
    257 static void WriteSignalMessage(int signo, int cpu,
    258                               void (*writerfn)(const char*)) {
    259  char buf[96];
    260  char on_cpu[32] = {0};
    261  if (cpu != -1) {
    262    snprintf(on_cpu, sizeof(on_cpu), " on cpu %d", cpu);
    263  }
    264  const char* const signal_string =
    265      debugging_internal::FailureSignalToString(signo);
    266  if (signal_string != nullptr && signal_string[0] != '\0') {
    267    snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
    268             signal_string,
    269             static_cast<long>(time(nullptr)),  // NOLINT(runtime/int)
    270             on_cpu);
    271  } else {
    272    snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
    273             signo, static_cast<long>(time(nullptr)),  // NOLINT(runtime/int)
    274             on_cpu);
    275  }
    276  writerfn(buf);
    277 }
    278 
    279 // `void*` might not be big enough to store `void(*)(const char*)`.
    280 struct WriterFnStruct {
    281  void (*writerfn)(const char*);
    282 };
    283 
    284 // Many of the absl::debugging_internal::Dump* functions in
    285 // examine_stack.h take a writer function pointer that has a void* arg
    286 // for historical reasons. failure_signal_handler_writer only takes a
    287 // data pointer. This function converts between these types.
    288 static void WriterFnWrapper(const char* data, void* arg) {
    289  static_cast<WriterFnStruct*>(arg)->writerfn(data);
    290 }
    291 
    292 // Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal
    293 // handlers. "noinline" so that GetStackFrames() skips the top-most stack
    294 // frame for this function.
    295 ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(
    296    void* ucontext, bool symbolize_stacktrace,
    297    void (*writerfn)(const char*, void*), void* writerfn_arg) {
    298  constexpr int kNumStackFrames = 32;
    299  void* stack[kNumStackFrames];
    300  int frame_sizes[kNumStackFrames];
    301  int min_dropped_frames;
    302  int depth = absl::GetStackFramesWithContext(
    303      stack, frame_sizes, kNumStackFrames,
    304      1,  // Do not include this function in stack trace.
    305      ucontext, &min_dropped_frames);
    306  absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace(
    307      absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes,
    308      depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg);
    309 }
    310 
    311 // Called by AbslFailureSignalHandler() to write the failure info. It is
    312 // called once with writerfn set to WriteToStderr() and then possibly
    313 // with writerfn set to the user provided function.
    314 static void WriteFailureInfo(int signo, void* ucontext, int cpu,
    315                             void (*writerfn)(const char*)) {
    316  WriterFnStruct writerfn_struct{writerfn};
    317  WriteSignalMessage(signo, cpu, writerfn);
    318  WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
    319                  &writerfn_struct);
    320 }
    321 
    322 // absl::SleepFor() can't be used here since AbslInternalSleepFor()
    323 // may be overridden to do something that isn't async-signal-safe on
    324 // some platforms.
    325 static void PortableSleepForSeconds(int seconds) {
    326 #ifdef _WIN32
    327  Sleep(static_cast<DWORD>(seconds * 1000));
    328 #else
    329  struct timespec sleep_time;
    330  sleep_time.tv_sec = seconds;
    331  sleep_time.tv_nsec = 0;
    332  while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
    333  }
    334 #endif
    335 }
    336 
    337 #ifdef ABSL_HAVE_ALARM
    338 // AbslFailureSignalHandler() installs this as a signal handler for
    339 // SIGALRM, then sets an alarm to be delivered to the program after a
    340 // set amount of time. If AbslFailureSignalHandler() hangs for more than
    341 // the alarm timeout, ImmediateAbortSignalHandler() will abort the
    342 // program.
    343 static void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); }
    344 #endif
    345 
    346 // absl::base_internal::GetTID() returns pid_t on most platforms, but
    347 // returns absl::base_internal::pid_t on Windows.
    348 using GetTidType = decltype(absl::base_internal::GetTID());
    349 ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);
    350 
    351 static int GetCpuNumber() {
    352 #ifdef ABSL_HAVE_SCHED_GETCPU
    353  return sched_getcpu();
    354 #elif defined(ABSL_HAVE_PTHREAD_CPU_NUMBER_NP)
    355  size_t cpu_num;
    356  if (pthread_cpu_number_np(&cpu_num) == 0) {
    357    return static_cast<int>(cpu_num);
    358  }
    359  return -1;
    360 #else
    361  return -1;
    362 #endif
    363 }
    364 
    365 #ifndef ABSL_HAVE_SIGACTION
    366 static void AbslFailureSignalHandler(int signo) {
    367  void* ucontext = nullptr;
    368 #else
    369 static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
    370 #endif
    371 
    372  const GetTidType this_tid = absl::base_internal::GetTID();
    373  GetTidType previous_failed_tid = 0;
    374  if (!failed_tid.compare_exchange_strong(previous_failed_tid, this_tid,
    375                                          std::memory_order_acq_rel,
    376                                          std::memory_order_relaxed)) {
    377    ABSL_RAW_LOG(
    378        ERROR,
    379        "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()",
    380        signo, absl::debugging_internal::GetProgramCounter(ucontext));
    381    if (this_tid != previous_failed_tid) {
    382      // Another thread is already in AbslFailureSignalHandler(), so wait
    383      // a bit for it to finish. If the other thread doesn't kill us,
    384      // we do so after sleeping.
    385      PortableSleepForSeconds(3);
    386      RaiseToDefaultHandler(signo);
    387      // The recursively raised signal may be blocked until we return.
    388      return;
    389    }
    390  }
    391 
    392  // Increase the chance that the CPU we report was the same CPU on which the
    393  // signal was received by doing this as early as possible, i.e. after
    394  // verifying that this is not a recursive signal handler invocation.
    395  int my_cpu = GetCpuNumber();
    396 
    397 #ifdef ABSL_HAVE_ALARM
    398  // Set an alarm to abort the program in case this code hangs or deadlocks.
    399  if (fsh_options.alarm_on_failure_secs > 0) {
    400    alarm(0);  // Cancel any existing alarms.
    401    signal(SIGALRM, ImmediateAbortSignalHandler);
    402    alarm(static_cast<unsigned int>(fsh_options.alarm_on_failure_secs));
    403  }
    404 #endif
    405 
    406  // First write to stderr.
    407  WriteFailureInfo(
    408      signo, ucontext, my_cpu, +[](const char* data) {
    409        absl::raw_log_internal::AsyncSignalSafeWriteError(data, strlen(data));
    410      });
    411 
    412  // Riskier code (because it is less likely to be async-signal-safe)
    413  // goes after this point.
    414  if (fsh_options.writerfn != nullptr) {
    415    WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn);
    416    fsh_options.writerfn(nullptr);
    417  }
    418 
    419  if (fsh_options.call_previous_handler) {
    420    RaiseToPreviousHandler(signo);
    421  } else {
    422    RaiseToDefaultHandler(signo);
    423  }
    424 }
    425 
    426 void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {
    427  fsh_options = options;
    428  for (auto& it : failure_signal_data) {
    429    InstallOneFailureHandler(&it, AbslFailureSignalHandler);
    430  }
    431 }
    432 
    433 ABSL_NAMESPACE_END
    434 }  // namespace absl