Line data Source code
1 : /* Copyright (c) 2013-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : /**
5 : * \file backtrace.c
6 : *
7 : * \brief Functions to produce backtraces on bugs, crashes, or assertion
8 : * failures.
9 : *
10 : * Currently, we've only got an implementation here using the backtrace()
11 : * family of functions, which are sometimes provided by libc and sometimes
12 : * provided by libexecinfo. We tie into the sigaction() backend in order to
13 : * detect crashes.
14 : *
15 : * This is one of the lowest-level modules, since nearly everything needs to
16 : * be able to log an error. As such, it doesn't call the log module or any
17 : * other higher-level modules directly.
18 : */
19 :
20 : #include "orconfig.h"
21 : #include "lib/err/torerr.h"
22 :
23 : #ifdef HAVE_EXECINFO_H
24 : #include <execinfo.h>
25 : #endif
26 : #ifdef HAVE_FCNTL_H
27 : #include <fcntl.h>
28 : #endif
29 : #ifdef HAVE_UNISTD_H
30 : #include <unistd.h>
31 : #endif
32 : #ifdef HAVE_SIGNAL_H
33 : #include <signal.h>
34 : #endif
35 : #ifdef HAVE_SYS_PARAM_H
36 : #include <sys/param.h>
37 : #endif
38 : #include <errno.h>
39 : #include <stdlib.h>
40 : #include <string.h>
41 : #include <stdio.h>
42 :
43 : #ifdef HAVE_CYGWIN_SIGNAL_H
44 : #include <cygwin/signal.h>
45 : #elif defined(HAVE_SYS_UCONTEXT_H)
46 : #include <sys/ucontext.h>
47 : #elif defined(HAVE_UCONTEXT_H)
48 : #include <ucontext.h>
49 : #endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
50 :
51 : #ifdef HAVE_PTHREAD_H
52 : #include <pthread.h>
53 : #endif
54 :
55 : #include "lib/cc/ctassert.h"
56 :
57 : #define BACKTRACE_PRIVATE
58 : #include "lib/err/backtrace.h"
59 :
60 : #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
61 : defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION) && \
62 : defined(HAVE_PTHREAD_H)
63 : #define USE_BACKTRACE
64 : #endif
65 :
66 : #if !defined(USE_BACKTRACE)
67 : #define NO_BACKTRACE_IMPL
68 : #endif
69 :
70 : // Redundant with util.h, but doing it here so we can avoid that dependency.
71 : #define raw_free free
72 :
73 : /** Version of Tor to report in backtrace messages. */
74 : static char bt_version[128] = "";
75 :
76 : #ifdef USE_BACKTRACE
77 :
78 : /** Largest stack depth to try to dump. */
79 : #define MAX_DEPTH 256
80 : /** The size of the callback buffer, so we can clear it in unlock_cb_buf(). */
81 : #define SIZEOF_CB_BUF (MAX_DEPTH * sizeof(void *))
82 : /** Protects cb_buf from concurrent access. Pthreads, since this code
83 : * is Unix-only, and since this code needs to be lowest-level. */
84 : static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
85 :
86 : /** Lock and return a static stack pointer buffer that can hold up to
87 : * MAX_DEPTH function pointers. */
88 : static void **
89 5556 : lock_cb_buf(void)
90 : {
91 : /* Lock the mutex first, before even declaring the buffer. */
92 5556 : pthread_mutex_lock(&cb_buf_mutex);
93 :
94 : /** Static allocation of stack to dump. This is static so we avoid stack
95 : * pressure. */
96 5556 : static void *cb_buf[MAX_DEPTH];
97 5556 : CTASSERT(SIZEOF_CB_BUF == sizeof(cb_buf));
98 5556 : memset(cb_buf, 0, SIZEOF_CB_BUF);
99 :
100 5556 : return cb_buf;
101 : }
102 :
103 : /** Unlock the static stack pointer buffer. */
104 : static void
105 5556 : unlock_cb_buf(void **cb_buf)
106 : {
107 5556 : memset(cb_buf, 0, SIZEOF_CB_BUF);
108 5556 : pthread_mutex_unlock(&cb_buf_mutex);
109 5556 : }
110 :
111 : /** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
112 : * log the correct function from which a signal was received with context
113 : * <b>ctx</b>. (When we get a signal, the current function will not have
114 : * called any other function, and will therefore have not pushed its address
115 : * onto the stack. Fortunately, we usually have the program counter in the
116 : * ucontext_t structure.
117 : */
118 : void
119 0 : clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
120 : {
121 : #ifdef PC_FROM_UCONTEXT
122 : #if defined(__linux__)
123 0 : const size_t n = 1;
124 : #elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
125 : || defined(__FreeBSD__)
126 : const size_t n = 2;
127 : #else
128 : const size_t n = 1;
129 : #endif /* defined(__linux__) || ... */
130 0 : if (depth <= n)
131 : return;
132 :
133 0 : stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
134 : #else /* !defined(PC_FROM_UCONTEXT) */
135 : (void) depth;
136 : (void) ctx;
137 : (void) stack;
138 : #endif /* defined(PC_FROM_UCONTEXT) */
139 : }
140 :
141 : /** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
142 : * that with a backtrace log. Send messages via the tor_log function at
143 : * logger". */
144 : void
145 2 : log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
146 : tor_log_fn logger)
147 : {
148 2 : size_t depth;
149 2 : char **symbols;
150 2 : size_t i;
151 :
152 2 : void **cb_buf = lock_cb_buf();
153 :
154 2 : depth = backtrace(cb_buf, MAX_DEPTH);
155 2 : symbols = backtrace_symbols(cb_buf, (int)depth);
156 :
157 2 : logger(severity, domain, "%s: %s. Stack trace:", bt_version, msg);
158 2 : if (!symbols) {
159 : /* LCOV_EXCL_START -- we can't provoke this. */
160 : logger(severity, domain, " Unable to generate backtrace.");
161 : goto done;
162 : /* LCOV_EXCL_STOP */
163 : }
164 28 : for (i=0; i < depth; ++i) {
165 26 : logger(severity, domain, " %s", symbols[i]);
166 : }
167 2 : raw_free(symbols);
168 :
169 2 : done:
170 2 : unlock_cb_buf(cb_buf);
171 2 : }
172 :
173 : static void crash_handler(int sig, siginfo_t *si, void *ctx_)
174 : __attribute__((noreturn));
175 :
176 : /** Signal handler: write a crash message with a stack trace, and die. */
177 : static void
178 0 : crash_handler(int sig, siginfo_t *si, void *ctx_)
179 : {
180 0 : char buf[40];
181 0 : size_t depth;
182 0 : ucontext_t *ctx = (ucontext_t *) ctx_;
183 0 : int n_fds, i;
184 0 : const int *fds = NULL;
185 :
186 0 : void **cb_buf = lock_cb_buf();
187 :
188 0 : (void) si;
189 :
190 0 : depth = backtrace(cb_buf, MAX_DEPTH);
191 : /* Clean up the top stack frame so we get the real function
192 : * name for the most recently failing function. */
193 0 : clean_backtrace(cb_buf, depth, ctx);
194 :
195 0 : format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
196 :
197 0 : tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
198 : NULL);
199 :
200 0 : n_fds = tor_log_get_sigsafe_err_fds(&fds);
201 0 : for (i=0; i < n_fds; ++i)
202 0 : backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
203 :
204 0 : unlock_cb_buf(cb_buf);
205 :
206 0 : tor_raw_abort_();
207 : }
208 :
209 : /** Write a backtrace to all of the emergency-error fds. */
210 : void
211 0 : dump_stack_symbols_to_error_fds(void)
212 : {
213 0 : int n_fds, i;
214 0 : const int *fds = NULL;
215 0 : size_t depth;
216 :
217 0 : void **cb_buf = lock_cb_buf();
218 :
219 0 : depth = backtrace(cb_buf, MAX_DEPTH);
220 :
221 0 : n_fds = tor_log_get_sigsafe_err_fds(&fds);
222 0 : for (i=0; i < n_fds; ++i)
223 0 : backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
224 :
225 0 : unlock_cb_buf(cb_buf);
226 0 : }
227 :
228 : /* The signals that we want our backtrace handler to trap */
229 : static int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
230 : SIGIO, -1 };
231 :
232 : /** Install signal handlers as needed so that when we crash, we produce a
233 : * useful stack trace. Return 0 on success, -errno on failure. */
234 : static int
235 5554 : install_bt_handler(void)
236 : {
237 5554 : int i, rv=0;
238 :
239 5554 : struct sigaction sa;
240 :
241 5554 : memset(&sa, 0, sizeof(sa));
242 5554 : sa.sa_sigaction = crash_handler;
243 5554 : sa.sa_flags = SA_SIGINFO;
244 5554 : sigfillset(&sa.sa_mask);
245 :
246 44432 : for (i = 0; trap_signals[i] >= 0; ++i) {
247 33324 : if (sigaction(trap_signals[i], &sa, NULL) == -1) {
248 : /* LCOV_EXCL_START */
249 : rv = -errno;
250 : /* LCOV_EXCL_STOP */
251 : }
252 : }
253 :
254 : {
255 : /* Now, generate (but do not log) a backtrace. This ensures that
256 : * libc has pre-loaded the symbols we need to dump things, so that later
257 : * reads won't be denied by the sandbox code */
258 5554 : char **symbols;
259 5554 : void **cb_buf = lock_cb_buf();
260 5554 : size_t depth = backtrace(cb_buf, MAX_DEPTH);
261 5554 : symbols = backtrace_symbols(cb_buf, (int) depth);
262 5554 : if (symbols)
263 5554 : raw_free(symbols);
264 5554 : unlock_cb_buf(cb_buf);
265 : }
266 :
267 5554 : return rv;
268 : }
269 :
270 : /** Uninstall crash handlers. */
271 : static void
272 236 : remove_bt_handler(void)
273 : {
274 236 : int i;
275 :
276 236 : struct sigaction sa;
277 :
278 236 : memset(&sa, 0, sizeof(sa));
279 236 : sa.sa_handler = SIG_DFL;
280 236 : sigfillset(&sa.sa_mask);
281 :
282 1888 : for (i = 0; trap_signals[i] >= 0; ++i) {
283 : /* remove_bt_handler() is called on shutdown, from low-level code.
284 : * It's not a fatal error, so we just ignore it. */
285 1416 : (void)sigaction(trap_signals[i], &sa, NULL);
286 : }
287 :
288 : /* cb_buf_mutex is statically initialised, so we can not destroy it.
289 : * If we destroy it, and then re-initialise tor, all our backtraces will
290 : * fail. */
291 236 : }
292 : #endif /* defined(USE_BACKTRACE) */
293 :
294 : #ifdef NO_BACKTRACE_IMPL
295 : void
296 : log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
297 : tor_log_fn logger)
298 : {
299 : logger(severity, domain, "%s: %s. (Stack trace not available)",
300 : bt_version, msg);
301 : }
302 :
303 : static int
304 : install_bt_handler(void)
305 : {
306 : return 0;
307 : }
308 :
309 : static void
310 : remove_bt_handler(void)
311 : {
312 : }
313 :
314 : void
315 : dump_stack_symbols_to_error_fds(void)
316 : {
317 : }
318 : #endif /* defined(NO_BACKTRACE_IMPL) */
319 :
320 : /** Return the tor version used for error messages on crashes.
321 : * Signal-safe: returns a pointer to a static array. */
322 : const char *
323 0 : get_tor_backtrace_version(void)
324 : {
325 0 : return bt_version;
326 : }
327 :
328 : /** Set up code to handle generating error messages on crashes. */
329 : int
330 5554 : configure_backtrace_handler(const char *tor_version)
331 : {
332 5554 : char version[128] = "Tor\0";
333 :
334 5554 : if (tor_version) {
335 5553 : int snp_rv = 0;
336 : /* We can't use strlcat() here, because it is defined in
337 : * string/compat_string.h on some platforms, and string uses torerr. */
338 5553 : snp_rv = snprintf(version, sizeof(version), "Tor %s", tor_version);
339 : /* It's safe to call raw_assert() here, because raw_assert() does not
340 : * call configure_backtrace_handler(). */
341 5553 : raw_assert(snp_rv < (int)sizeof(version));
342 5553 : raw_assert(snp_rv >= 0);
343 : }
344 :
345 5554 : char *str_rv = NULL;
346 : /* We can't use strlcpy() here, see the note about strlcat() above. */
347 5554 : str_rv = strncpy(bt_version, version, sizeof(bt_version) - 1);
348 : /* We must terminate bt_version, then raw_assert(), because raw_assert()
349 : * uses bt_version. */
350 5554 : bt_version[sizeof(bt_version) - 1] = 0;
351 5554 : raw_assert(str_rv == bt_version);
352 :
353 5554 : return install_bt_handler();
354 : }
355 :
356 : /** Perform end-of-process cleanup for code that generates error messages on
357 : * crashes. */
358 : void
359 236 : clean_up_backtrace_handler(void)
360 : {
361 236 : remove_bt_handler();
362 236 : }
|