tor

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

torerr.c (9129B)


      1 /* Copyright (c) 2001, Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file torerr.c
      9 *
     10 * \brief Handling code for unrecoverable emergencies, at a lower level
     11 *   than the logging code.
     12 *
     13 * There are plenty of places that things can go wrong in Tor's backend
     14 * libraries: the allocator can fail, the locking subsystem can fail, and so
     15 * on.  But since these subsystems are used themselves by the logging module,
     16 * they can't use the logging code directly to report their errors.
     17 *
     18 * As a workaround, the logging code provides this module with a set of raw
     19 * fds to be used for reporting errors in the lowest-level Tor code.
     20 */
     21 
     22 #include "orconfig.h"
     23 #include <stdarg.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <stdio.h>
     27 #ifdef HAVE_SYS_TIME_H
     28 #include <sys/time.h>
     29 #endif
     30 #ifdef HAVE_TIME_H
     31 #include <time.h>
     32 #endif
     33 #ifdef HAVE_UNISTD_H
     34 #include <unistd.h>
     35 #endif
     36 #ifdef HAVE_SYS_TYPES_H
     37 #include <sys/types.h>
     38 #endif
     39 
     40 #include "lib/err/torerr.h"
     41 #include "lib/err/backtrace.h"
     42 
     43 /** Array of fds to log crash-style warnings to. */
     44 static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
     45 /** The number of elements used in sigsafe_log_fds */
     46 static int n_sigsafe_log_fds = 1;
     47 /** Log granularity in milliseconds. */
     48 static int log_granularity = 1000;
     49 
     50 /** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
     51 * on failure. */
     52 static int
     53 tor_log_err_sigsafe_write(const char *s)
     54 {
     55  int i;
     56  ssize_t r;
     57  size_t len = strlen(s);
     58  int err = 0;
     59  for (i=0; i < n_sigsafe_log_fds; ++i) {
     60    r = write(sigsafe_log_fds[i], s, len);
     61    err += (r != (ssize_t)len);
     62  }
     63  return err ? -1 : 0;
     64 }
     65 
     66 /** Given a list of string arguments ending with a NULL, writes them
     67 * to our logs and to stderr (if possible).  This function is safe to call
     68 * from within a signal handler. */
     69 void
     70 tor_log_err_sigsafe(const char *m, ...)
     71 {
     72  va_list ap;
     73  const char *x;
     74  char timebuf[33];
     75  time_t now = time(NULL);
     76 
     77  if (!m)
     78    return;
     79  if (log_granularity >= 2000) {
     80    int g = log_granularity / 1000;
     81    now -= now % g;
     82  }
     83  timebuf[0] = now < 0 ? '-' : ' ';
     84  if (now < 0) now = -now;
     85  timebuf[1] = '\0';
     86  format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
     87  tor_log_err_sigsafe_write("\n=========================================="
     88                             "================== T=");
     89  tor_log_err_sigsafe_write(timebuf);
     90  tor_log_err_sigsafe_write("\n");
     91  tor_log_err_sigsafe_write(m);
     92  va_start(ap, m);
     93  while ((x = va_arg(ap, const char*))) {
     94    tor_log_err_sigsafe_write(x);
     95  }
     96  va_end(ap);
     97 }
     98 
     99 /** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
    100 * inside a signal handler or other emergency condition. Return the number of
    101 * elements in the array. */
    102 int
    103 tor_log_get_sigsafe_err_fds(const int **out)
    104 {
    105  *out = sigsafe_log_fds;
    106  return n_sigsafe_log_fds;
    107 }
    108 
    109 /**
    110 * Update the list of fds that get errors from inside a signal handler or
    111 * other emergency condition. Ignore any beyond the first
    112 * TOR_SIGSAFE_LOG_MAX_FDS.
    113 *
    114 * These fds must remain open even after the log module has shut down. (And
    115 * they should remain open even while logs are being reconfigured.) Therefore,
    116 * any fds closed by the log module should be dup()ed, and the duplicate fd
    117 * should be given to the err module in fds. In particular, the log module
    118 * closes the file log fds, but does not close the stdio log fds.
    119 *
    120 * If fds is NULL or n is 0, clears the list of error fds.
    121 */
    122 void
    123 tor_log_set_sigsafe_err_fds(const int *fds, int n)
    124 {
    125  if (n > TOR_SIGSAFE_LOG_MAX_FDS) {
    126    n = TOR_SIGSAFE_LOG_MAX_FDS;
    127  }
    128 
    129  /* Clear the entire array. This code mitigates against some race conditions,
    130   * but there are still some races here:
    131   * - err logs are disabled while the array is cleared, and
    132   * - a thread can read the old value of n_sigsafe_log_fds, then read a
    133   *   partially written array.
    134   * We could fix these races using atomics, but atomics use the err module. */
    135  n_sigsafe_log_fds = 0;
    136  memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
    137  if (fds && n > 0) {
    138    memcpy(sigsafe_log_fds, fds, n * sizeof(int));
    139    n_sigsafe_log_fds = n;
    140  }
    141 }
    142 
    143 /**
    144 * Reset the list of emergency error fds to its default.
    145 */
    146 void
    147 tor_log_reset_sigsafe_err_fds(void)
    148 {
    149  int fds[] = { STDERR_FILENO };
    150  tor_log_set_sigsafe_err_fds(fds, 1);
    151 }
    152 
    153 /**
    154 * Flush the list of fds that get errors from inside a signal handler or
    155 * other emergency condition. These fds are shared with the logging code:
    156 * flushing them also flushes the log buffers.
    157 *
    158 * This function is safe to call during signal handlers.
    159 */
    160 void
    161 tor_log_flush_sigsafe_err_fds(void)
    162 {
    163  /* If we don't have fsync() in unistd.h, we can't flush the logs. */
    164 #ifdef HAVE_FSYNC
    165  int n_fds, i;
    166  const int *fds = NULL;
    167 
    168  n_fds = tor_log_get_sigsafe_err_fds(&fds);
    169  for (i = 0; i < n_fds; ++i) {
    170    /* This function is called on error and on shutdown, so we don't log, or
    171     * take any other action, if fsync() fails. */
    172    (void)fsync(fds[i]);
    173  }
    174 #endif /* defined(HAVE_FSYNC) */
    175 }
    176 
    177 /**
    178 * Set the granularity (in ms) to use when reporting fatal errors outside
    179 * the logging system.
    180 */
    181 void
    182 tor_log_sigsafe_err_set_granularity(int ms)
    183 {
    184  log_granularity = ms;
    185 }
    186 
    187 /**
    188 * Log an emergency assertion failure message.
    189 *
    190 * This kind of message is safe to send from within a log handler,
    191 * a signal handler, or other emergency situation.
    192 */
    193 void
    194 tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
    195                              const char *msg)
    196 {
    197  char linebuf[16];
    198  format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
    199  tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed in ",
    200                      get_tor_backtrace_version(), " at ",
    201                      file, ":", linebuf, ": ", expr, "\n", NULL);
    202  if (msg) {
    203    tor_log_err_sigsafe_write(msg);
    204    tor_log_err_sigsafe_write("\n");
    205  }
    206 
    207  dump_stack_symbols_to_error_fds();
    208 
    209  /* Some platforms (macOS, maybe others?) can swallow the last write before an
    210   * abort. This issue is probably caused by a race condition between write
    211   * buffer cache flushing, and process termination. So we write an extra
    212   * newline, to make sure that the message always gets through. */
    213  tor_log_err_sigsafe_write("\n");
    214 }
    215 
    216 /**
    217 * Call the abort() function to kill the current process with a fatal
    218 * error. But first, flush the raw error file descriptors, so error messages
    219 * are written before process termination.
    220 **/
    221 void
    222 tor_raw_abort_(void)
    223 {
    224  tor_log_flush_sigsafe_err_fds();
    225  abort();
    226 }
    227 
    228 /* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
    229 * in range 2..16 inclusive. */
    230 static int
    231 format_number_sigsafe(unsigned long x, char *buf, int buf_len,
    232                      unsigned int radix)
    233 {
    234  unsigned long tmp;
    235  int len;
    236  char *cp;
    237 
    238  /* NOT tor_assert. This needs to be safe to run from within a signal
    239   * handler, and from within the 'tor_assert() has failed' code.  Not even
    240   * raw_assert(), since raw_assert() calls this function on failure. */
    241  if (radix < 2 || radix > 16)
    242    return 0;
    243 
    244  /* Count how many digits we need. */
    245  tmp = x;
    246  len = 1;
    247  while (tmp >= radix) {
    248    tmp /= radix;
    249    ++len;
    250  }
    251 
    252  /* Not long enough */
    253  if (!buf || len >= buf_len)
    254    return 0;
    255 
    256  cp = buf + len;
    257  *cp = '\0';
    258  do {
    259    unsigned digit = (unsigned) (x % radix);
    260    if (cp <= buf) {
    261      /* Not tor_assert(); see above. */
    262      tor_raw_abort_();
    263    }
    264    --cp;
    265    *cp = "0123456789ABCDEF"[digit];
    266    x /= radix;
    267  } while (x);
    268 
    269  /* NOT tor_assert; see above. */
    270  if (cp != buf) {
    271    tor_raw_abort_(); // LCOV_EXCL_LINE
    272  }
    273 
    274  return len;
    275 }
    276 
    277 /**
    278 * Helper function to output hex numbers from within a signal handler.
    279 *
    280 * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
    281 * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
    282 * written, not counting the terminal NUL.
    283 *
    284 * If there is insufficient space, write nothing and return 0.
    285 *
    286 * This accepts an unsigned int because format_helper_exit_status() needs to
    287 * call it with a signed int and an unsigned char, and since the C standard
    288 * does not guarantee that an int is wider than a char (an int must be at
    289 * least 16 bits but it is permitted for a char to be that wide as well), we
    290 * can't assume a signed int is sufficient to accommodate an unsigned char.
    291 * Thus, callers will still need to add any required '-' to the final string.
    292 *
    293 * For most purposes, you'd want to use tor_snprintf("%x") instead of this
    294 * function; it's designed to be used in code paths where you can't call
    295 * arbitrary C functions.
    296 */
    297 int
    298 format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
    299 {
    300  return format_number_sigsafe(x, buf, buf_len, 16);
    301 }
    302 
    303 /** As format_hex_number_sigsafe, but format the number in base 10. */
    304 int
    305 format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
    306 {
    307  return format_number_sigsafe(x, buf, buf_len, 10);
    308 }