Tor 0.4.9.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. */
44static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
45/** The number of elements used in sigsafe_log_fds */
46static int n_sigsafe_log_fds = 1;
47/** Log granularity in milliseconds. */
48static 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. */
52static 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. */
69void
70tor_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. */
102int
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 */
122void
123tor_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. */
136 memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
137 if (fds && n > 0) {
138 memcpy(sigsafe_log_fds, fds, n * sizeof(int));
140 }
141}
142
143/**
144 * Reset the list of emergency error fds to its default.
145 */
146void
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 */
160void
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 */
181void
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 */
193void
194tor_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 ",
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 **/
221void
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. */
230static int
231format_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. */
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 */
297int
298format_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. */
304int
305format_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