1 /* Copyright (c) 2013-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 * \brief Functions to produce backtraces on bugs, crashes, or assertion
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
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.
21 #include "lib/err/torerr.h"
23 #ifdef HAVE_EXECINFO_H
35 #ifdef HAVE_SYS_PARAM_H
36 #include <sys/param.h>
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)
49 #endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
55 #define EXPOSE_CLEAN_BACKTRACE
56 #include "lib/err/backtrace.h"
57 #include "lib/err/torerr.h"
59 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
60 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
64 #if !defined(USE_BACKTRACE)
65 #define NO_BACKTRACE_IMPL
68 // Redundant with util.h, but doing it here so we can avoid that dependency.
72 /** Version of Tor to report in backtrace messages. */
73 static char bt_version
[128] = "";
75 /** Largest stack depth to try to dump. */
77 /** Static allocation of stack to dump. This is static so we avoid stack
79 static void *cb_buf
[MAX_DEPTH
];
80 /** Protects cb_buf from concurrent access. Pthreads, since this code
81 * is Unix-only, and since this code needs to be lowest-level. */
82 static pthread_mutex_t cb_buf_mutex
= PTHREAD_MUTEX_INITIALIZER
;
84 /** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
85 * log the correct function from which a signal was received with context
86 * <b>ctx</b>. (When we get a signal, the current function will not have
87 * called any other function, and will therefore have not pushed its address
88 * onto the stack. Fortunately, we usually have the program counter in the
89 * ucontext_t structure.
92 clean_backtrace(void **stack
, size_t depth
, const ucontext_t
*ctx
)
94 #ifdef PC_FROM_UCONTEXT
95 #if defined(__linux__)
97 #elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
98 || defined(__FreeBSD__)
102 #endif /* defined(__linux__) || ... */
106 stack
[n
] = (void*) ctx
->PC_FROM_UCONTEXT
;
107 #else /* !(defined(PC_FROM_UCONTEXT)) */
111 #endif /* defined(PC_FROM_UCONTEXT) */
114 /** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
115 * that with a backtrace log. Send messages via the tor_log function at
118 log_backtrace_impl(int severity
, uint64_t domain
, const char *msg
,
125 pthread_mutex_lock(&cb_buf_mutex
);
127 depth
= backtrace(cb_buf
, MAX_DEPTH
);
128 symbols
= backtrace_symbols(cb_buf
, (int)depth
);
130 logger(severity
, domain
, "%s. Stack trace:", msg
);
132 /* LCOV_EXCL_START -- we can't provoke this. */
133 logger(severity
, domain
, " Unable to generate backtrace.");
137 for (i
=0; i
< depth
; ++i
) {
138 logger(severity
, domain
, " %s", symbols
[i
]);
143 pthread_mutex_unlock(&cb_buf_mutex
);
146 static void crash_handler(int sig
, siginfo_t
*si
, void *ctx_
)
147 __attribute__((noreturn
));
149 /** Signal handler: write a crash message with a stack trace, and die. */
151 crash_handler(int sig
, siginfo_t
*si
, void *ctx_
)
155 ucontext_t
*ctx
= (ucontext_t
*) ctx_
;
157 const int *fds
= NULL
;
161 depth
= backtrace(cb_buf
, MAX_DEPTH
);
162 /* Clean up the top stack frame so we get the real function
163 * name for the most recently failing function. */
164 clean_backtrace(cb_buf
, depth
, ctx
);
166 format_dec_number_sigsafe((unsigned)sig
, buf
, sizeof(buf
));
168 tor_log_err_sigsafe(bt_version
, " died: Caught signal ", buf
, "\n",
171 n_fds
= tor_log_get_sigsafe_err_fds(&fds
);
172 for (i
=0; i
< n_fds
; ++i
)
173 backtrace_symbols_fd(cb_buf
, (int)depth
, fds
[i
]);
178 /** Write a backtrace to all of the emergency-error fds. */
180 dump_stack_symbols_to_error_fds(void)
183 const int *fds
= NULL
;
186 depth
= backtrace(cb_buf
, MAX_DEPTH
);
188 n_fds
= tor_log_get_sigsafe_err_fds(&fds
);
189 for (i
=0; i
< n_fds
; ++i
)
190 backtrace_symbols_fd(cb_buf
, (int)depth
, fds
[i
]);
193 /** Install signal handlers as needed so that when we crash, we produce a
194 * useful stack trace. Return 0 on success, -errno on failure. */
196 install_bt_handler(const char *software
)
198 int trap_signals
[] = { SIGSEGV
, SIGILL
, SIGFPE
, SIGBUS
, SIGSYS
,
202 strncpy(bt_version
, software
, sizeof(bt_version
) - 1);
203 bt_version
[sizeof(bt_version
) - 1] = 0;
207 memset(&sa
, 0, sizeof(sa
));
208 sa
.sa_sigaction
= crash_handler
;
209 sa
.sa_flags
= SA_SIGINFO
;
210 sigfillset(&sa
.sa_mask
);
212 for (i
= 0; trap_signals
[i
] >= 0; ++i
) {
213 if (sigaction(trap_signals
[i
], &sa
, NULL
) == -1) {
214 /* LCOV_EXCL_START */
221 /* Now, generate (but do not log) a backtrace. This ensures that
222 * libc has pre-loaded the symbols we need to dump things, so that later
223 * reads won't be denied by the sandbox code */
225 size_t depth
= backtrace(cb_buf
, MAX_DEPTH
);
226 symbols
= backtrace_symbols(cb_buf
, (int) depth
);
234 /** Uninstall crash handlers. */
236 remove_bt_handler(void)
239 #endif /* defined(USE_BACKTRACE) */
241 #ifdef NO_BACKTRACE_IMPL
243 log_backtrace_impl(int severity
, uint64_t domain
, const char *msg
,
246 logger(severity
, domain
, "%s. (Stack trace not available)", msg
);
250 install_bt_handler(const char *software
)
257 remove_bt_handler(void)
262 dump_stack_symbols_to_error_fds(void)
265 #endif /* defined(NO_BACKTRACE_IMPL) */
267 /** Set up code to handle generating error messages on crashes. */
269 configure_backtrace_handler(const char *tor_version
)
271 char version
[128] = "Tor\0";
274 snprintf(version
, sizeof(version
), "Tor %s", tor_version
);
277 return install_bt_handler(version
);
280 /** Perform end-of-process cleanup for code that generates error messages on
283 clean_up_backtrace_handler(void)