tor  0.4.0.1-alpha
backtrace.c
Go to the documentation of this file.
1 /* Copyright (c) 2013-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
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 #define EXPOSE_CLEAN_BACKTRACE
56 #include "lib/err/backtrace.h"
57 #include "lib/err/torerr.h"
58 
59 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
60  defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
61 #define USE_BACKTRACE
62 #endif
63 
64 #if !defined(USE_BACKTRACE)
65 #define NO_BACKTRACE_IMPL
66 #endif
67 
68 // Redundant with util.h, but doing it here so we can avoid that dependency.
69 #define raw_free free
70 
71 #ifdef USE_BACKTRACE
72 
73 static char bt_version[128] = "";
74 
76 #define MAX_DEPTH 256
77 
79 static void *cb_buf[MAX_DEPTH];
82 static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
83 
91 void
92 clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
93 {
94 #ifdef PC_FROM_UCONTEXT
95 #if defined(__linux__)
96  const size_t n = 1;
97 #elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
98  || defined(__FreeBSD__)
99  const size_t n = 2;
100 #else
101  const size_t n = 1;
102 #endif /* defined(__linux__) || ... */
103  if (depth <= n)
104  return;
105 
106  stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
107 #else /* !(defined(PC_FROM_UCONTEXT)) */
108  (void) depth;
109  (void) ctx;
110  (void) stack;
111 #endif /* defined(PC_FROM_UCONTEXT) */
112 }
113 
117 void
118 log_backtrace_impl(int severity, int domain, const char *msg,
119  tor_log_fn logger)
120 {
121  size_t depth;
122  char **symbols;
123  size_t i;
124 
125  pthread_mutex_lock(&cb_buf_mutex);
126 
127  depth = backtrace(cb_buf, MAX_DEPTH);
128  symbols = backtrace_symbols(cb_buf, (int)depth);
129 
130  logger(severity, domain, "%s. Stack trace:", msg);
131  if (!symbols) {
132  /* LCOV_EXCL_START -- we can't provoke this. */
133  logger(severity, domain, " Unable to generate backtrace.");
134  goto done;
135  /* LCOV_EXCL_STOP */
136  }
137  for (i=0; i < depth; ++i) {
138  logger(severity, domain, " %s", symbols[i]);
139  }
140  raw_free(symbols);
141 
142  done:
143  pthread_mutex_unlock(&cb_buf_mutex);
144 }
145 
146 static void crash_handler(int sig, siginfo_t *si, void *ctx_)
147  __attribute__((noreturn));
148 
150 static void
151 crash_handler(int sig, siginfo_t *si, void *ctx_)
152 {
153  char buf[40];
154  size_t depth;
155  ucontext_t *ctx = (ucontext_t *) ctx_;
156  int n_fds, i;
157  const int *fds = NULL;
158 
159  (void) si;
160 
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);
165 
166  format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
167 
168  tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
169  NULL);
170 
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]);
174 
175  abort();
176 }
177 
179 void
180 dump_stack_symbols_to_error_fds(void)
181 {
182  int n_fds, i;
183  const int *fds = NULL;
184  size_t depth;
185 
186  depth = backtrace(cb_buf, MAX_DEPTH);
187 
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]);
191 }
192 
195 static int
196 install_bt_handler(const char *software)
197 {
198  int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
199  SIGIO, -1 };
200  int i, rv=0;
201 
202  strncpy(bt_version, software, sizeof(bt_version) - 1);
203  bt_version[sizeof(bt_version) - 1] = 0;
204 
205  struct sigaction sa;
206 
207  memset(&sa, 0, sizeof(sa));
208  sa.sa_sigaction = crash_handler;
209  sa.sa_flags = SA_SIGINFO;
210  sigfillset(&sa.sa_mask);
211 
212  for (i = 0; trap_signals[i] >= 0; ++i) {
213  if (sigaction(trap_signals[i], &sa, NULL) == -1) {
214  /* LCOV_EXCL_START */
215  rv = -errno;
216  /* LCOV_EXCL_STOP */
217  }
218  }
219 
220  {
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 */
224  char **symbols;
225  size_t depth = backtrace(cb_buf, MAX_DEPTH);
226  symbols = backtrace_symbols(cb_buf, (int) depth);
227  if (symbols)
228  raw_free(symbols);
229  }
230 
231  return rv;
232 }
233 
235 static void
236 remove_bt_handler(void)
237 {
238 }
239 #endif /* defined(USE_BACKTRACE) */
240 
241 #ifdef NO_BACKTRACE_IMPL
242 void
243 log_backtrace_impl(int severity, int domain, const char *msg,
244  tor_log_fn logger)
245 {
246  logger(severity, domain, "%s. (Stack trace not available)", msg);
247 }
248 
249 static int
250 install_bt_handler(const char *software)
251 {
252  (void) software;
253  return 0;
254 }
255 
256 static void
257 remove_bt_handler(void)
258 {
259 }
260 
261 void
262 dump_stack_symbols_to_error_fds(void)
263 {
264 }
265 #endif /* defined(NO_BACKTRACE_IMPL) */
266 
268 int
269 configure_backtrace_handler(const char *tor_version)
270 {
271  char version[128] = "Tor\0";
272 
273  if (tor_version) {
274  snprintf(version, sizeof(version), "Tor %s", tor_version);
275  }
276 
277  return install_bt_handler(version);
278 }
279 
282 void
284 {
285  remove_bt_handler();
286 }
Header for backtrace.c.
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
int configure_backtrace_handler(const char *tor_version)
Definition: backtrace.c:269
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:245
void clean_up_backtrace_handler(void)
Definition: backtrace.c:283
Headers for torerr.c.
int tor_log_get_sigsafe_err_fds(const int **out)
Definition: torerr.c:103