tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

backtrace.c (9496B)


      1 /* Copyright (c) 2013-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file backtrace.c
      6 *
      7 * \brief Functions to produce backtraces on bugs, crashes, or assertion
      8 * failures.
      9 *
     10 * Currently, we've only got an implementation here using the backtrace()
     11 * family of functions, which are sometimes provided by libc and sometimes
     12 * provided by libexecinfo.  We tie into the sigaction() backend in order to
     13 * detect crashes.
     14 *
     15 * This is one of the lowest-level modules, since nearly everything needs to
     16 * be able to log an error.  As such, it doesn't call the log module or any
     17 * other higher-level modules directly.
     18 */
     19 
     20 #include "orconfig.h"
     21 #include "lib/err/torerr.h"
     22 
     23 #ifdef HAVE_EXECINFO_H
     24 #include <execinfo.h>
     25 #endif
     26 #ifdef HAVE_FCNTL_H
     27 #include <fcntl.h>
     28 #endif
     29 #ifdef HAVE_UNISTD_H
     30 #include <unistd.h>
     31 #endif
     32 #ifdef HAVE_SIGNAL_H
     33 #include <signal.h>
     34 #endif
     35 #ifdef HAVE_SYS_PARAM_H
     36 #include <sys/param.h>
     37 #endif
     38 #include <errno.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <stdio.h>
     42 
     43 #ifdef HAVE_CYGWIN_SIGNAL_H
     44 #include <cygwin/signal.h>
     45 #elif defined(HAVE_SYS_UCONTEXT_H)
     46 #include <sys/ucontext.h>
     47 #elif defined(HAVE_UCONTEXT_H)
     48 #include <ucontext.h>
     49 #endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
     50 
     51 #ifdef HAVE_PTHREAD_H
     52 #include <pthread.h>
     53 #endif
     54 
     55 #include "lib/cc/ctassert.h"
     56 
     57 #define BACKTRACE_PRIVATE
     58 #include "lib/err/backtrace.h"
     59 
     60 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
     61  defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION) && \
     62  defined(HAVE_PTHREAD_H)
     63 #define USE_BACKTRACE
     64 #endif
     65 
     66 #if !defined(USE_BACKTRACE)
     67 #define NO_BACKTRACE_IMPL
     68 #endif
     69 
     70 // Redundant with util.h, but doing it here so we can avoid that dependency.
     71 #define raw_free free
     72 
     73 /** Version of Tor to report in backtrace messages. */
     74 static char bt_version[128] = "";
     75 
     76 #ifdef USE_BACKTRACE
     77 
     78 /** Largest stack depth to try to dump. */
     79 #define MAX_DEPTH 256
     80 /** The size of the callback buffer, so we can clear it in unlock_cb_buf(). */
     81 #define SIZEOF_CB_BUF (MAX_DEPTH * sizeof(void *))
     82 /** Protects cb_buf from concurrent access. Pthreads, since this code
     83 * is Unix-only, and since this code needs to be lowest-level. */
     84 static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
     85 
     86 /** Lock and return a static stack pointer buffer that can hold up to
     87 *  MAX_DEPTH function pointers. */
     88 static void **
     89 lock_cb_buf(void)
     90 {
     91  /* Lock the mutex first, before even declaring the buffer. */
     92  pthread_mutex_lock(&cb_buf_mutex);
     93 
     94  /** Static allocation of stack to dump. This is static so we avoid stack
     95   * pressure. */
     96  static void *cb_buf[MAX_DEPTH];
     97  CTASSERT(SIZEOF_CB_BUF == sizeof(cb_buf));
     98  memset(cb_buf, 0, SIZEOF_CB_BUF);
     99 
    100  return cb_buf;
    101 }
    102 
    103 /** Unlock the static stack pointer buffer. */
    104 static void
    105 unlock_cb_buf(void **cb_buf)
    106 {
    107  memset(cb_buf, 0, SIZEOF_CB_BUF);
    108  pthread_mutex_unlock(&cb_buf_mutex);
    109 }
    110 
    111 /** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
    112 * log the correct function from which a signal was received with context
    113 * <b>ctx</b>.  (When we get a signal, the current function will not have
    114 * called any other function, and will therefore have not pushed its address
    115 * onto the stack.  Fortunately, we usually have the program counter in the
    116 * ucontext_t structure.
    117 */
    118 void
    119 clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
    120 {
    121 #ifdef PC_FROM_UCONTEXT
    122 #if defined(__linux__)
    123  const size_t n = 1;
    124 #elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
    125  || defined(__FreeBSD__)
    126  const size_t n = 2;
    127 #else
    128  const size_t n = 1;
    129 #endif /* defined(__linux__) || ... */
    130  if (depth <= n)
    131    return;
    132 
    133  stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
    134 #else /* !defined(PC_FROM_UCONTEXT) */
    135  (void) depth;
    136  (void) ctx;
    137  (void) stack;
    138 #endif /* defined(PC_FROM_UCONTEXT) */
    139 }
    140 
    141 /** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
    142 * that with a backtrace log.  Send messages via the tor_log function at
    143 * logger". */
    144 void
    145 log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
    146                   tor_log_fn logger)
    147 {
    148  size_t depth;
    149  char **symbols;
    150  size_t i;
    151 
    152  void **cb_buf = lock_cb_buf();
    153 
    154  depth = backtrace(cb_buf, MAX_DEPTH);
    155  symbols = backtrace_symbols(cb_buf, (int)depth);
    156 
    157  logger(severity, domain, "%s: %s. Stack trace:", bt_version, msg);
    158  if (!symbols) {
    159    /* LCOV_EXCL_START -- we can't provoke this. */
    160    logger(severity, domain, "    Unable to generate backtrace.");
    161    goto done;
    162    /* LCOV_EXCL_STOP */
    163  }
    164  for (i=0; i < depth; ++i) {
    165    logger(severity, domain, "    %s", symbols[i]);
    166  }
    167  raw_free(symbols);
    168 
    169 done:
    170  unlock_cb_buf(cb_buf);
    171 }
    172 
    173 static void crash_handler(int sig, siginfo_t *si, void *ctx_)
    174  __attribute__((noreturn));
    175 
    176 /** Signal handler: write a crash message with a stack trace, and die. */
    177 static void
    178 crash_handler(int sig, siginfo_t *si, void *ctx_)
    179 {
    180  char buf[40];
    181  size_t depth;
    182  ucontext_t *ctx = (ucontext_t *) ctx_;
    183  int n_fds, i;
    184  const int *fds = NULL;
    185 
    186  void **cb_buf = lock_cb_buf();
    187 
    188  (void) si;
    189 
    190  depth = backtrace(cb_buf, MAX_DEPTH);
    191  /* Clean up the top stack frame so we get the real function
    192   * name for the most recently failing function. */
    193  clean_backtrace(cb_buf, depth, ctx);
    194 
    195  format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
    196 
    197  tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
    198                      NULL);
    199 
    200  n_fds = tor_log_get_sigsafe_err_fds(&fds);
    201  for (i=0; i < n_fds; ++i)
    202    backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
    203 
    204  unlock_cb_buf(cb_buf);
    205 
    206  tor_raw_abort_();
    207 }
    208 
    209 /** Write a backtrace to all of the emergency-error fds. */
    210 void
    211 dump_stack_symbols_to_error_fds(void)
    212 {
    213  int n_fds, i;
    214  const int *fds = NULL;
    215  size_t depth;
    216 
    217  void **cb_buf = lock_cb_buf();
    218 
    219  depth = backtrace(cb_buf, MAX_DEPTH);
    220 
    221  n_fds = tor_log_get_sigsafe_err_fds(&fds);
    222  for (i=0; i < n_fds; ++i)
    223    backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
    224 
    225  unlock_cb_buf(cb_buf);
    226 }
    227 
    228 /* The signals that we want our backtrace handler to trap */
    229 static int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
    230  SIGIO, -1 };
    231 
    232 /** Install signal handlers as needed so that when we crash, we produce a
    233 * useful stack trace. Return 0 on success, -errno on failure. */
    234 static int
    235 install_bt_handler(void)
    236 {
    237  int i, rv=0;
    238 
    239  struct sigaction sa;
    240 
    241  memset(&sa, 0, sizeof(sa));
    242  sa.sa_sigaction = crash_handler;
    243  sa.sa_flags = SA_SIGINFO;
    244  sigfillset(&sa.sa_mask);
    245 
    246  for (i = 0; trap_signals[i] >= 0; ++i) {
    247    if (sigaction(trap_signals[i], &sa, NULL) == -1) {
    248      /* LCOV_EXCL_START */
    249      rv = -errno;
    250      /* LCOV_EXCL_STOP */
    251    }
    252  }
    253 
    254  {
    255    /* Now, generate (but do not log) a backtrace.  This ensures that
    256     * libc has pre-loaded the symbols we need to dump things, so that later
    257     * reads won't be denied by the sandbox code */
    258    char **symbols;
    259    void **cb_buf = lock_cb_buf();
    260    size_t depth = backtrace(cb_buf, MAX_DEPTH);
    261    symbols = backtrace_symbols(cb_buf, (int) depth);
    262    if (symbols)
    263      raw_free(symbols);
    264    unlock_cb_buf(cb_buf);
    265  }
    266 
    267  return rv;
    268 }
    269 
    270 /** Uninstall crash handlers. */
    271 static void
    272 remove_bt_handler(void)
    273 {
    274  int i;
    275 
    276  struct sigaction sa;
    277 
    278  memset(&sa, 0, sizeof(sa));
    279  sa.sa_handler = SIG_DFL;
    280  sigfillset(&sa.sa_mask);
    281 
    282  for (i = 0; trap_signals[i] >= 0; ++i) {
    283    /* remove_bt_handler() is called on shutdown, from low-level code.
    284     * It's not a fatal error, so we just ignore it. */
    285    (void)sigaction(trap_signals[i], &sa, NULL);
    286  }
    287 
    288  /* cb_buf_mutex is statically initialised, so we can not destroy it.
    289   * If we destroy it, and then re-initialise tor, all our backtraces will
    290   * fail. */
    291 }
    292 #endif /* defined(USE_BACKTRACE) */
    293 
    294 #ifdef NO_BACKTRACE_IMPL
    295 void
    296 log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
    297                   tor_log_fn logger)
    298 {
    299  logger(severity, domain, "%s: %s. (Stack trace not available)",
    300         bt_version, msg);
    301 }
    302 
    303 static int
    304 install_bt_handler(void)
    305 {
    306  return 0;
    307 }
    308 
    309 static void
    310 remove_bt_handler(void)
    311 {
    312 }
    313 
    314 void
    315 dump_stack_symbols_to_error_fds(void)
    316 {
    317 }
    318 #endif /* defined(NO_BACKTRACE_IMPL) */
    319 
    320 /** Return the tor version used for error messages on crashes.
    321 * Signal-safe: returns a pointer to a static array. */
    322 const char *
    323 get_tor_backtrace_version(void)
    324 {
    325  return bt_version;
    326 }
    327 
    328 /** Set up code to handle generating error messages on crashes. */
    329 int
    330 configure_backtrace_handler(const char *tor_version)
    331 {
    332  char version[128] = "Tor\0";
    333 
    334  if (tor_version) {
    335    int snp_rv = 0;
    336    /* We can't use strlcat() here, because it is defined in
    337     * string/compat_string.h on some platforms, and string uses torerr. */
    338    snp_rv = snprintf(version, sizeof(version), "Tor %s", tor_version);
    339    /* It's safe to call raw_assert() here, because raw_assert() does not
    340     * call configure_backtrace_handler(). */
    341    raw_assert(snp_rv < (int)sizeof(version));
    342    raw_assert(snp_rv >= 0);
    343  }
    344 
    345  char *str_rv = NULL;
    346  /* We can't use strlcpy() here, see the note about strlcat() above. */
    347  str_rv = strncpy(bt_version, version, sizeof(bt_version) - 1);
    348  /* We must terminate bt_version, then raw_assert(), because raw_assert()
    349   * uses bt_version. */
    350  bt_version[sizeof(bt_version) - 1] = 0;
    351  raw_assert(str_rv == bt_version);
    352 
    353  return install_bt_handler();
    354 }
    355 
    356 /** Perform end-of-process cleanup for code that generates error messages on
    357 * crashes.  */
    358 void
    359 clean_up_backtrace_handler(void)
    360 {
    361  remove_bt_handler();
    362 }