Line data Source code
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 10 : tor_log_err_sigsafe_write(const char *s)
54 : {
55 10 : int i;
56 10 : ssize_t r;
57 10 : size_t len = strlen(s);
58 10 : int err = 0;
59 30 : for (i=0; i < n_sigsafe_log_fds; ++i) {
60 20 : r = write(sigsafe_log_fds[i], s, len);
61 20 : err += (r != (ssize_t)len);
62 : }
63 10 : 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 2 : tor_log_err_sigsafe(const char *m, ...)
71 : {
72 2 : va_list ap;
73 2 : const char *x;
74 2 : char timebuf[33];
75 2 : time_t now = time(NULL);
76 :
77 2 : if (!m)
78 0 : return;
79 2 : if (log_granularity >= 2000) {
80 1 : int g = log_granularity / 1000;
81 1 : now -= now % g;
82 : }
83 2 : timebuf[0] = now < 0 ? '-' : ' ';
84 2 : if (now < 0) now = -now;
85 2 : timebuf[1] = '\0';
86 2 : format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
87 2 : tor_log_err_sigsafe_write("\n=========================================="
88 : "================== T=");
89 2 : tor_log_err_sigsafe_write(timebuf);
90 2 : tor_log_err_sigsafe_write("\n");
91 2 : tor_log_err_sigsafe_write(m);
92 2 : va_start(ap, m);
93 4 : while ((x = va_arg(ap, const char*))) {
94 2 : tor_log_err_sigsafe_write(x);
95 : }
96 2 : 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 240 : tor_log_get_sigsafe_err_fds(const int **out)
104 : {
105 240 : *out = sigsafe_log_fds;
106 240 : 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 5566 : tor_log_set_sigsafe_err_fds(const int *fds, int n)
124 : {
125 5566 : 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 5566 : n_sigsafe_log_fds = 0;
136 5566 : memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
137 5566 : if (fds && n > 0) {
138 5566 : memcpy(sigsafe_log_fds, fds, n * sizeof(int));
139 5566 : n_sigsafe_log_fds = n;
140 : }
141 5566 : }
142 :
143 : /**
144 : * Reset the list of emergency error fds to its default.
145 : */
146 : void
147 5553 : tor_log_reset_sigsafe_err_fds(void)
148 : {
149 5553 : int fds[] = { STDERR_FILENO };
150 5553 : tor_log_set_sigsafe_err_fds(fds, 1);
151 5553 : }
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 235 : 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 235 : int n_fds, i;
166 235 : const int *fds = NULL;
167 :
168 235 : n_fds = tor_log_get_sigsafe_err_fds(&fds);
169 705 : 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 235 : (void)fsync(fds[i]);
173 : }
174 : #endif /* defined(HAVE_FSYNC) */
175 235 : }
176 :
177 : /**
178 : * Set the granularity (in ms) to use when reporting fatal errors outside
179 : * the logging system.
180 : */
181 : void
182 14 : tor_log_sigsafe_err_set_granularity(int ms)
183 : {
184 14 : log_granularity = ms;
185 14 : }
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 0 : tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
195 : const char *msg)
196 : {
197 0 : char linebuf[16];
198 0 : format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
199 0 : tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed in ",
200 : get_tor_backtrace_version(), " at ",
201 : file, ":", linebuf, ": ", expr, "\n", NULL);
202 0 : if (msg) {
203 0 : tor_log_err_sigsafe_write(msg);
204 0 : tor_log_err_sigsafe_write("\n");
205 : }
206 :
207 0 : 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 0 : tor_log_err_sigsafe_write("\n");
214 0 : }
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 0 : tor_raw_abort_(void)
223 : {
224 0 : tor_log_flush_sigsafe_err_fds();
225 0 : 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 31 : format_number_sigsafe(unsigned long x, char *buf, int buf_len,
232 : unsigned int radix)
233 : {
234 31 : unsigned long tmp;
235 31 : int len;
236 31 : 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 31 : if (radix < 2 || radix > 16)
242 : return 0;
243 :
244 : /* Count how many digits we need. */
245 : tmp = x;
246 : len = 1;
247 163 : while (tmp >= radix) {
248 132 : tmp /= radix;
249 132 : ++len;
250 : }
251 :
252 : /* Not long enough */
253 31 : if (!buf || len >= buf_len)
254 : return 0;
255 :
256 27 : cp = buf + len;
257 27 : *cp = '\0';
258 153 : do {
259 153 : unsigned digit = (unsigned) (x % radix);
260 153 : if (cp <= buf) {
261 : /* Not tor_assert(); see above. */
262 0 : tor_raw_abort_();
263 : }
264 153 : --cp;
265 153 : *cp = "0123456789ABCDEF"[digit];
266 153 : x /= radix;
267 153 : } while (x);
268 :
269 : /* NOT tor_assert; see above. */
270 27 : 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 11 : format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
299 : {
300 11 : 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 20 : format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
306 : {
307 20 : return format_number_sigsafe(x, buf, buf_len, 10);
308 : }
|