Tor 0.4.9.0-alpha-dev
backtrace.c
Go to the documentation of this file.
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. */
74static 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. */
84static 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. */
88static void **
89lock_cb_buf(void)
90{
91 /* Lock the mutex first, before even declaring the buffer. */
92 pthread_mutex_lock(&cb_buf_mutex);
93
94 /** Static allocation of stack to dump. This is static so we avoid stack
95 * pressure. */
96 static void *cb_buf[MAX_DEPTH];
97 CTASSERT(SIZEOF_CB_BUF == sizeof(cb_buf));
98 memset(cb_buf, 0, SIZEOF_CB_BUF);
99
100 return cb_buf;
101}
102
103/** Unlock the static stack pointer buffer. */
104static void
105unlock_cb_buf(void **cb_buf)
106{
107 memset(cb_buf, 0, SIZEOF_CB_BUF);
108 pthread_mutex_unlock(&cb_buf_mutex);
109}
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 */
118void
119clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
120{
121#ifdef PC_FROM_UCONTEXT
122#if defined(__linux__)
123 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 if (depth <= n)
131 return;
132
133 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". */
144void
145log_backtrace_impl(int severity, log_domain_mask_t domain, const char *msg,
146 tor_log_fn logger)
147{
148 size_t depth;
149 char **symbols;
150 size_t i;
151
152 void **cb_buf = lock_cb_buf();
153
154 depth = backtrace(cb_buf, MAX_DEPTH);
155 symbols = backtrace_symbols(cb_buf, (int)depth);
156
157 logger(severity, domain, "%s: %s. Stack trace:", bt_version, msg);
158 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 for (i=0; i < depth; ++i) {
165 logger(severity, domain, " %s", symbols[i]);
166 }
167 raw_free(symbols);
168
169 done:
170 unlock_cb_buf(cb_buf);
171}
172
173static 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. */
177static void
178crash_handler(int sig, siginfo_t *si, void *ctx_)
179{
180 char buf[40];
181 size_t depth;
182 ucontext_t *ctx = (ucontext_t *) ctx_;
183 int n_fds, i;
184 const int *fds = NULL;
185
186 void **cb_buf = lock_cb_buf();
187
188 (void) si;
189
190 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 clean_backtrace(cb_buf, depth, ctx);
194
195 format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
196
197 tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
198 NULL);
199
200 n_fds = tor_log_get_sigsafe_err_fds(&fds);
201 for (i=0; i < n_fds; ++i)
202 backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
203
204 unlock_cb_buf(cb_buf);
205
207}
208
209/** Write a backtrace to all of the emergency-error fds. */
210void
211dump_stack_symbols_to_error_fds(void)
212{
213 int n_fds, i;
214 const int *fds = NULL;
215 size_t depth;
216
217 void **cb_buf = lock_cb_buf();
218
219 depth = backtrace(cb_buf, MAX_DEPTH);
220
221 n_fds = tor_log_get_sigsafe_err_fds(&fds);
222 for (i=0; i < n_fds; ++i)
223 backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
224
225 unlock_cb_buf(cb_buf);
226}
227
228/* The signals that we want our backtrace handler to trap */
229static 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. */
234static int
235install_bt_handler(void)
236{
237 int i, rv=0;
238
239 struct sigaction sa;
240
241 memset(&sa, 0, sizeof(sa));
242 sa.sa_sigaction = crash_handler;
243 sa.sa_flags = SA_SIGINFO;
244 sigfillset(&sa.sa_mask);
245
246 for (i = 0; trap_signals[i] >= 0; ++i) {
247 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 char **symbols;
259 void **cb_buf = lock_cb_buf();
260 size_t depth = backtrace(cb_buf, MAX_DEPTH);
261 symbols = backtrace_symbols(cb_buf, (int) depth);
262 if (symbols)
263 raw_free(symbols);
264 unlock_cb_buf(cb_buf);
265 }
266
267 return rv;
268}
269
270/** Uninstall crash handlers. */
271static void
272remove_bt_handler(void)
273{
274 int i;
275
276 struct sigaction sa;
277
278 memset(&sa, 0, sizeof(sa));
279 sa.sa_handler = SIG_DFL;
280 sigfillset(&sa.sa_mask);
281
282 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 (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}
292#endif /* defined(USE_BACKTRACE) */
293
294#ifdef NO_BACKTRACE_IMPL
295void
296log_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
303static int
304install_bt_handler(void)
305{
306 return 0;
307}
308
309static void
310remove_bt_handler(void)
311{
312}
313
314void
315dump_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. */
322const char *
324{
325 return bt_version;
326}
327
328/** Set up code to handle generating error messages on crashes. */
329int
330configure_backtrace_handler(const char *tor_version)
331{
332 char version[128] = "Tor\0";
333
334 if (tor_version) {
335 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 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 raw_assert(snp_rv < (int)sizeof(version));
342 raw_assert(snp_rv >= 0);
343 }
344
345 char *str_rv = NULL;
346 /* We can't use strlcpy() here, see the note about strlcat() above. */
347 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 bt_version[sizeof(bt_version) - 1] = 0;
351 raw_assert(str_rv == bt_version);
352
353 return install_bt_handler();
354}
355
356/** Perform end-of-process cleanup for code that generates error messages on
357 * crashes. */
358void
360{
361 remove_bt_handler();
362}
static char bt_version[128]
Definition: backtrace.c:74
const char * get_tor_backtrace_version(void)
Definition: backtrace.c:323
int configure_backtrace_handler(const char *tor_version)
Definition: backtrace.c:330
void clean_up_backtrace_handler(void)
Definition: backtrace.c:359
Header for backtrace.c.
Compile-time assertions: CTASSERT(expression).
CTASSERT(NUMBER_SECOND_GUARDS< 20)
uint64_t log_domain_mask_t
Definition: logging_types.h:21
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:305
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
void tor_raw_abort_(void)
Definition: torerr.c:222
int tor_log_get_sigsafe_err_fds(const int **out)
Definition: torerr.c:103
Headers for torerr.c.