Tor  0.4.7.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-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
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  * 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
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
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) {
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. */
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
223 {
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 }
const char * get_tor_backtrace_version(void)
Definition: backtrace.c:323
Header for backtrace.c.
Definitions for timing-related constants.
void tor_log_flush_sigsafe_err_fds(void)
Definition: torerr.c:161
void tor_log_sigsafe_err_set_granularity(int ms)
Definition: torerr.c:182
void tor_log_reset_sigsafe_err_fds(void)
Definition: torerr.c:147
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:305
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
Definition: torerr.c:123
void tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr, const char *msg)
Definition: torerr.c:194
int format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:298
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS]
Definition: torerr.c:44
void tor_raw_abort_(void)
Definition: torerr.c:222
static int log_granularity
Definition: torerr.c:48
static int n_sigsafe_log_fds
Definition: torerr.c:46
int tor_log_get_sigsafe_err_fds(const int **out)
Definition: torerr.c:103
static int tor_log_err_sigsafe_write(const char *s)
Definition: torerr.c:53
Headers for torerr.c.
#define TOR_SIGSAFE_LOG_MAX_FDS
Definition: torerr.h:37