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 }