Tor  0.4.3.0-alpha-dev
torerr.c
Go to the documentation of this file.
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-2019, 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
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=");
92  va_start(ap, m);
93  while ((x = va_arg(ap, const char*))) {
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
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) {
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
148 {
149  int fds[] = { STDERR_FILENO };
151 }
152 
153 /**
154  * Close 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  * closing them flushes the log buffers, and prevents any further logging.
157  *
158  * This function closes stderr, so it should only be called immediately before
159  * process shutdown.
160  */
161 void
163 {
164  int n_fds, i;
165  const int *fds = NULL;
166 
167  n_fds = tor_log_get_sigsafe_err_fds(&fds);
168  for (i = 0; i < n_fds; ++i) {
169  /* tor_log_close_sigsafe_err_fds_on_error() is called on error and on
170  * shutdown, so we can't log or take any useful action if close()
171  * fails. */
172  (void)close(fds[i]);
173  }
174 
175  /* Don't even try logging, we've closed all the log fds. */
177 }
178 
179 /**
180  * Set the granularity (in ms) to use when reporting fatal errors outside
181  * the logging system.
182  */
183 void
185 {
186  log_granularity = ms;
187 }
188 
189 /**
190  * Log an emergency assertion failure message.
191  *
192  * This kind of message is safe to send from within a log handler,
193  * a signal handler, or other emergency situation.
194  */
195 void
196 tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
197  const char *msg)
198 {
199  char linebuf[16];
200  format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
201  tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed in ",
202  get_tor_backtrace_version(), " at ",
203  file, ":", linebuf, ": ", expr, "\n", NULL);
204  if (msg) {
207  }
208 
209  dump_stack_symbols_to_error_fds();
210 
211  /* Some platforms (macOS, maybe others?) can swallow the last write before an
212  * abort. This issue is probably caused by a race condition between write
213  * buffer cache flushing, and process termination. So we write an extra
214  * newline, to make sure that the message always gets through. */
216 }
217 
218 /**
219  * Call the abort() function to kill the current process with a fatal
220  * error. But first, close the raw error file descriptors, so error messages
221  * are written before process termination.
222  **/
223 void
225 {
227  abort();
228 }
229 
230 /* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
231  * in range 2..16 inclusive. */
232 static int
233 format_number_sigsafe(unsigned long x, char *buf, int buf_len,
234  unsigned int radix)
235 {
236  unsigned long tmp;
237  int len;
238  char *cp;
239 
240  /* NOT tor_assert. This needs to be safe to run from within a signal
241  * handler, and from within the 'tor_assert() has failed' code. Not even
242  * raw_assert(), since raw_assert() calls this function on failure. */
243  if (radix < 2 || radix > 16)
244  return 0;
245 
246  /* Count how many digits we need. */
247  tmp = x;
248  len = 1;
249  while (tmp >= radix) {
250  tmp /= radix;
251  ++len;
252  }
253 
254  /* Not long enough */
255  if (!buf || len >= buf_len)
256  return 0;
257 
258  cp = buf + len;
259  *cp = '\0';
260  do {
261  unsigned digit = (unsigned) (x % radix);
262  if (cp <= buf) {
263  /* Not tor_assert(); see above. */
264  tor_raw_abort_();
265  }
266  --cp;
267  *cp = "0123456789ABCDEF"[digit];
268  x /= radix;
269  } while (x);
270 
271  /* NOT tor_assert; see above. */
272  if (cp != buf) {
273  tor_raw_abort_(); // LCOV_EXCL_LINE
274  }
275 
276  return len;
277 }
278 
279 /**
280  * Helper function to output hex numbers from within a signal handler.
281  *
282  * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
283  * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
284  * written, not counting the terminal NUL.
285  *
286  * If there is insufficient space, write nothing and return 0.
287  *
288  * This accepts an unsigned int because format_helper_exit_status() needs to
289  * call it with a signed int and an unsigned char, and since the C standard
290  * does not guarantee that an int is wider than a char (an int must be at
291  * least 16 bits but it is permitted for a char to be that wide as well), we
292  * can't assume a signed int is sufficient to accommodate an unsigned char.
293  * Thus, callers will still need to add any required '-' to the final string.
294  *
295  * For most purposes, you'd want to use tor_snprintf("%x") instead of this
296  * function; it's designed to be used in code paths where you can't call
297  * arbitrary C functions.
298  */
299 int
300 format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
301 {
302  return format_number_sigsafe(x, buf, buf_len, 16);
303 }
304 
305 /** As format_hex_number_sigsafe, but format the number in base 10. */
306 int
307 format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
308 {
309  return format_number_sigsafe(x, buf, buf_len, 10);
310 }
void tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr, const char *msg)
Definition: torerr.c:196
Header for backtrace.c.
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
Definitions for timing-related constants.
void tor_log_sigsafe_err_set_granularity(int ms)
Definition: torerr.c:184
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
Definition: torerr.c:123
static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS]
Definition: torerr.c:44
int format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:300
static int log_granularity
Definition: torerr.c:48
static int tor_log_err_sigsafe_write(const char *s)
Definition: torerr.c:53
#define TOR_SIGSAFE_LOG_MAX_FDS
Definition: torerr.h:37
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:307
void tor_log_close_sigsafe_err_fds(void)
Definition: torerr.c:162
void tor_log_reset_sigsafe_err_fds(void)
Definition: torerr.c:147
Headers for torerr.c.
static int n_sigsafe_log_fds
Definition: torerr.c:46
int tor_log_get_sigsafe_err_fds(const int **out)
Definition: torerr.c:103
void tor_raw_abort_(void)
Definition: torerr.c:224
const char * get_tor_backtrace_version(void)
Definition: backtrace.c:323