aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-06-21 09:53:08 -0400
committerNick Mathewson <nickm@torproject.org>2018-06-21 10:47:11 -0400
commit2cfcb7b364541c27749ae0df73eabd7a56797f93 (patch)
tree1fb03761e4631f1d5edd893fc9164a49ff8981b6 /src/common
parentb2346b12019c45288bbae3bd009fe0bafe80ff58 (diff)
downloadtor-2cfcb7b364541c27749ae0df73eabd7a56797f93.tar.gz
tor-2cfcb7b364541c27749ae0df73eabd7a56797f93.zip
Extract error functionality into a new lowest-level library.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/backtrace.c282
-rw-r--r--src/common/backtrace.h29
-rw-r--r--src/common/include.am4
-rw-r--r--src/common/torerr.c229
-rw-r--r--src/common/torerr.h47
5 files changed, 0 insertions, 591 deletions
diff --git a/src/common/backtrace.c b/src/common/backtrace.c
deleted file mode 100644
index d83cbba0e8..0000000000
--- a/src/common/backtrace.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* Copyright (c) 2013-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file backtrace.c
- *
- * \brief Functions to produce backtraces on bugs, crashes, or assertion
- * failures.
- *
- * Currently, we've only got an implementation here using the backtrace()
- * family of functions, which are sometimes provided by libc and sometimes
- * provided by libexecinfo. We tie into the sigaction() backend in order to
- * detect crashes.
- */
-
-#include "orconfig.h"
-#include "common/torerr.h"
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_CYGWIN_SIGNAL_H
-#include <cygwin/signal.h>
-#elif defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h>
-#endif /* defined(HAVE_CYGWIN_SIGNAL_H) || ... */
-
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-
-#define EXPOSE_CLEAN_BACKTRACE
-#include "common/backtrace.h"
-#include "common/torerr.h"
-
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
-#define USE_BACKTRACE
-#endif
-
-#if !defined(USE_BACKTRACE)
-#define NO_BACKTRACE_IMPL
-#endif
-
-// Redundant with util.h, but doing it here so we can avoid that dependency.
-#define raw_free free
-
-#ifdef USE_BACKTRACE
-/** Version of Tor to report in backtrace messages. */
-static char bt_version[128] = "";
-
-/** Largest stack depth to try to dump. */
-#define MAX_DEPTH 256
-/** Static allocation of stack to dump. This is static so we avoid stack
- * pressure. */
-static void *cb_buf[MAX_DEPTH];
-/** Protects cb_buf from concurrent access. Pthreads, since this code
- * is Unix-only, and since this code needs to be lowest-level. */
-static pthread_mutex_t cb_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
- * log the correct function from which a signal was received with context
- * <b>ctx</b>. (When we get a signal, the current function will not have
- * called any other function, and will therefore have not pushed its address
- * onto the stack. Fortunately, we usually have the program counter in the
- * ucontext_t structure.
- */
-void
-clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx)
-{
-#ifdef PC_FROM_UCONTEXT
-#if defined(__linux__)
- const size_t n = 1;
-#elif defined(__darwin__) || defined(__APPLE__) || defined(OpenBSD) \
- || defined(__FreeBSD__)
- const size_t n = 2;
-#else
- const size_t n = 1;
-#endif /* defined(__linux__) || ... */
- if (depth <= n)
- return;
-
- stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
-#else /* !(defined(PC_FROM_UCONTEXT)) */
- (void) depth;
- (void) ctx;
- (void) stack;
-#endif /* defined(PC_FROM_UCONTEXT) */
-}
-
-/** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
- * that with a backtrace log. Send messages via the tor_log function at
- * logger". */
-void
-log_backtrace_impl(int severity, int domain, const char *msg,
- tor_log_fn logger)
-{
- size_t depth;
- char **symbols;
- size_t i;
-
- pthread_mutex_lock(&cb_buf_mutex);
-
- depth = backtrace(cb_buf, MAX_DEPTH);
- symbols = backtrace_symbols(cb_buf, (int)depth);
-
- logger(severity, domain, "%s. Stack trace:", msg);
- if (!symbols) {
- /* LCOV_EXCL_START -- we can't provoke this. */
- logger(severity, domain, " Unable to generate backtrace.");
- goto done;
- /* LCOV_EXCL_STOP */
- }
- for (i=0; i < depth; ++i) {
- logger(severity, domain, " %s", symbols[i]);
- }
- raw_free(symbols);
-
- done:
- pthread_mutex_unlock(&cb_buf_mutex);
-}
-
-static void crash_handler(int sig, siginfo_t *si, void *ctx_)
- __attribute__((noreturn));
-
-/** Signal handler: write a crash message with a stack trace, and die. */
-static void
-crash_handler(int sig, siginfo_t *si, void *ctx_)
-{
- char buf[40];
- size_t depth;
- ucontext_t *ctx = (ucontext_t *) ctx_;
- int n_fds, i;
- const int *fds = NULL;
-
- (void) si;
-
- depth = backtrace(cb_buf, MAX_DEPTH);
- /* Clean up the top stack frame so we get the real function
- * name for the most recently failing function. */
- clean_backtrace(cb_buf, depth, ctx);
-
- format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
-
- tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
- NULL);
-
- n_fds = tor_log_get_sigsafe_err_fds(&fds);
- for (i=0; i < n_fds; ++i)
- backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
-
- abort();
-}
-
-/** Write a backtrace to all of the emergency-error fds. */
-void
-dump_stack_symbols_to_error_fds(void)
-{
- int n_fds, i;
- const int *fds = NULL;
- size_t depth;
-
- depth = backtrace(cb_buf, MAX_DEPTH);
-
- n_fds = tor_log_get_sigsafe_err_fds(&fds);
- for (i=0; i < n_fds; ++i)
- backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
-}
-
-/** Install signal handlers as needed so that when we crash, we produce a
- * useful stack trace. Return 0 on success, -errno on failure. */
-static int
-install_bt_handler(const char *software)
-{
- int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
- SIGIO, -1 };
- int i, rv=0;
-
- strncpy(bt_version, software, sizeof(bt_version) - 1);
- bt_version[sizeof(bt_version) - 1] = 0;
-
- struct sigaction sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = crash_handler;
- sa.sa_flags = SA_SIGINFO;
- sigfillset(&sa.sa_mask);
-
- for (i = 0; trap_signals[i] >= 0; ++i) {
- if (sigaction(trap_signals[i], &sa, NULL) == -1) {
- /* LCOV_EXCL_START */
- rv = -errno;
- /* LCOV_EXCL_STOP */
- }
- }
-
- {
- /* Now, generate (but do not log) a backtrace. This ensures that
- * libc has pre-loaded the symbols we need to dump things, so that later
- * reads won't be denied by the sandbox code */
- char **symbols;
- size_t depth = backtrace(cb_buf, MAX_DEPTH);
- symbols = backtrace_symbols(cb_buf, (int) depth);
- if (symbols)
- raw_free(symbols);
- }
-
- return rv;
-}
-
-/** Uninstall crash handlers. */
-static void
-remove_bt_handler(void)
-{
-}
-#endif /* defined(USE_BACKTRACE) */
-
-#ifdef NO_BACKTRACE_IMPL
-void
-log_backtrace_impl(int severity, int domain, const char *msg,
- tor_log_fn logger)
-{
- logger(severity, domain, "%s. (Stack trace not available)", msg);
-}
-
-static int
-install_bt_handler(const char *software)
-{
- (void) software;
- return 0;
-}
-
-static void
-remove_bt_handler(void)
-{
-}
-
-void
-dump_stack_symbols_to_error_fds(void)
-{
-}
-#endif /* defined(NO_BACKTRACE_IMPL) */
-
-/** Set up code to handle generating error messages on crashes. */
-int
-configure_backtrace_handler(const char *tor_version)
-{
- char version[128];
- strncpy(version, "Tor", sizeof(version)-1);
-
- if (tor_version) {
- strncat(version, " ", sizeof(version)-1);
- strncat(version, tor_version, sizeof(version)-1);
- }
-
- version[sizeof(version) - 1] = 0;
-
- return install_bt_handler(version);
-}
-
-/** Perform end-of-process cleanup for code that generates error messages on
- * crashes. */
-void
-clean_up_backtrace_handler(void)
-{
- remove_bt_handler();
-}
diff --git a/src/common/backtrace.h b/src/common/backtrace.h
deleted file mode 100644
index 0a145fc92d..0000000000
--- a/src/common/backtrace.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (c) 2013-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-#ifndef TOR_BACKTRACE_H
-#define TOR_BACKTRACE_H
-
-#include "orconfig.h"
-#include "common/compat_compiler.h"
-
-typedef void (*tor_log_fn)(int, unsigned, const char *fmt, ...)
- CHECK_PRINTF(3,4);
-
-void log_backtrace_impl(int severity, int domain, const char *msg,
- tor_log_fn logger);
-int configure_backtrace_handler(const char *tor_version);
-void clean_up_backtrace_handler(void);
-void dump_stack_symbols_to_error_fds(void);
-
-#define log_backtrace(sev, dom, msg) \
- log_backtrace_impl((sev), (dom), (msg), tor_log)
-
-#ifdef EXPOSE_CLEAN_BACKTRACE
-#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
-void clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx);
-#endif
-#endif /* defined(EXPOSE_CLEAN_BACKTRACE) */
-
-#endif /* !defined(TOR_BACKTRACE_H) */
diff --git a/src/common/include.am b/src/common/include.am
index 8afec9c054..5337034861 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -82,7 +82,6 @@ src_common_libor_ctime_testing_a_CFLAGS = @CFLAGS_CONSTTIME@ $(TEST_CFLAGS)
LIBOR_A_SRC = \
src/common/address.c \
src/common/address_set.c \
- src/common/backtrace.c \
src/common/buffers.c \
src/common/compat.c \
src/common/compat_threads.c \
@@ -99,7 +98,6 @@ LIBOR_A_SRC = \
src/common/sandbox.c \
src/common/storagedir.c \
src/common/token_bucket.c \
- src/common/torerr.c \
src/common/workqueue.c \
$(libor_extra_source) \
$(threads_impl_source) \
@@ -161,7 +159,6 @@ src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
COMMONHEADERS = \
src/common/address.h \
src/common/address_set.h \
- src/common/backtrace.h \
src/common/buffers.h \
src/common/buffers_tls.h \
src/common/aes.h \
@@ -203,7 +200,6 @@ COMMONHEADERS = \
src/common/testsupport.h \
src/common/timers.h \
src/common/token_bucket.h \
- src/common/torerr.h \
src/common/torint.h \
src/common/torlog.h \
src/common/tortls.h \
diff --git a/src/common/torerr.c b/src/common/torerr.c
deleted file mode 100644
index 0e0c4db355..0000000000
--- a/src/common/torerr.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file torerr.c
- *
- * \brief Handling code for unrecoverable emergencies, at a lower level
- * than the logging code.
- */
-
-#include "orconfig.h"
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "common/torerr.h"
-#include "common/backtrace.h"
-
-/** Array of fds to log crash-style warnings to. */
-static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
-/** The number of elements used in sigsafe_log_fds */
-static int n_sigsafe_log_fds = 1;
-/** Log granularity in milliseconds. */
-static int log_granularity = 1000;
-
-/** Write <b>s</b> to each element of sigsafe_log_fds. Return 0 on success, -1
- * on failure. */
-static int
-tor_log_err_sigsafe_write(const char *s)
-{
- int i;
- ssize_t r;
- size_t len = strlen(s);
- int err = 0;
- for (i=0; i < n_sigsafe_log_fds; ++i) {
- r = write(sigsafe_log_fds[i], s, len);
- err += (r != (ssize_t)len);
- }
- return err ? -1 : 0;
-}
-
-/** Given a list of string arguments ending with a NULL, writes them
- * to our logs and to stderr (if possible). This function is safe to call
- * from within a signal handler. */
-void
-tor_log_err_sigsafe(const char *m, ...)
-{
- va_list ap;
- const char *x;
- char timebuf[33];
- time_t now = time(NULL);
-
- if (!m)
- return;
- if (log_granularity >= 2000) {
- int g = log_granularity / 1000;
- now -= now % g;
- }
- timebuf[0] = now < 0 ? '-' : ' ';
- if (now < 0) now = -now;
- timebuf[1] = '\0';
- format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
- tor_log_err_sigsafe_write("\n=========================================="
- "================== T=");
- tor_log_err_sigsafe_write(timebuf);
- tor_log_err_sigsafe_write("\n");
- tor_log_err_sigsafe_write(m);
- va_start(ap, m);
- while ((x = va_arg(ap, const char*))) {
- tor_log_err_sigsafe_write(x);
- }
- va_end(ap);
-}
-
-/** Set *<b>out</b> to a pointer to an array of the fds to log errors to from
- * inside a signal handler or other emergency condition. Return the number of
- * elements in the array. */
-int
-tor_log_get_sigsafe_err_fds(const int **out)
-{
- *out = sigsafe_log_fds;
- return n_sigsafe_log_fds;
-}
-
-/**
- * Update the list of fds that get errors from inside a signal handler or
- * other emergency condition. Ignore any beyond the first
- * TOR_SIGSAFE_LOG_MAX_FDS.
- */
-void
-tor_log_set_sigsafe_err_fds(const int *fds, int n)
-{
- if (n > TOR_SIGSAFE_LOG_MAX_FDS) {
- n = TOR_SIGSAFE_LOG_MAX_FDS;
- }
-
- memcpy(sigsafe_log_fds, fds, n * sizeof(int));
- n_sigsafe_log_fds = n;
-}
-
-/**
- * Set the granularity (in ms) to use when reporting fatal errors outside
- * the logging system.
- */
-void
-tor_log_sigsafe_err_set_granularity(int ms)
-{
- log_granularity = ms;
-}
-
-/**
- * Log an emergency assertion failure message.
- *
- * This kind of message is safe to send from within a log handler,
- * a signal handler, or other emergency situation.
- */
-void
-tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
- const char *msg)
-{
- char linebuf[16];
- format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
- tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed at ",
- file, ":", linebuf, ": ", expr, NULL);
- if (msg) {
- tor_log_err_sigsafe_write(msg);
- tor_log_err_sigsafe_write("\n");
- }
-
- dump_stack_symbols_to_error_fds();
-}
-
-/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
- * in range 2..16 inclusive. */
-static int
-format_number_sigsafe(unsigned long x, char *buf, int buf_len,
- unsigned int radix)
-{
- unsigned long tmp;
- int len;
- char *cp;
-
- /* NOT tor_assert. This needs to be safe to run from within a signal
- * handler, and from within the 'tor_assert() has failed' code. Not even
- * raw_assert(), since raw_assert() calls this function on failure. */
- if (radix < 2 || radix > 16)
- return 0;
-
- /* Count how many digits we need. */
- tmp = x;
- len = 1;
- while (tmp >= radix) {
- tmp /= radix;
- ++len;
- }
-
- /* Not long enough */
- if (!buf || len >= buf_len)
- return 0;
-
- cp = buf + len;
- *cp = '\0';
- do {
- unsigned digit = (unsigned) (x % radix);
- if (cp <= buf) {
- /* Not tor_assert(); see above. */
- abort();
- }
- --cp;
- *cp = "0123456789ABCDEF"[digit];
- x /= radix;
- } while (x);
-
- /* NOT tor_assert; see above. */
- if (cp != buf) {
- abort(); // LCOV_EXCL_LINE
- }
-
- return len;
-}
-
-/**
- * Helper function to output hex numbers from within a signal handler.
- *
- * Writes the nul-terminated hexadecimal digits of <b>x</b> into a buffer
- * <b>buf</b> of size <b>buf_len</b>, and return the actual number of digits
- * written, not counting the terminal NUL.
- *
- * If there is insufficient space, write nothing and return 0.
- *
- * This accepts an unsigned int because format_helper_exit_status() needs to
- * call it with a signed int and an unsigned char, and since the C standard
- * does not guarantee that an int is wider than a char (an int must be at
- * least 16 bits but it is permitted for a char to be that wide as well), we
- * can't assume a signed int is sufficient to accommodate an unsigned char.
- * Thus, format_helper_exit_status() will still need to emit any require '-'
- * on its own.
- *
- * For most purposes, you'd want to use tor_snprintf("%x") instead of this
- * function; it's designed to be used in code paths where you can't call
- * arbitrary C functions.
- */
-int
-format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 16);
-}
-
-/** As format_hex_number_sigsafe, but format the number in base 10. */
-int
-format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
-{
- return format_number_sigsafe(x, buf, buf_len, 10);
-}
diff --git a/src/common/torerr.h b/src/common/torerr.h
deleted file mode 100644
index 10d9f481c0..0000000000
--- a/src/common/torerr.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (c) 2001, Matej Pfajfar.
- * Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file torerr.h
- *
- * \brief Headers for torerr.c.
- **/
-
-#ifndef TOR_TORERR_H
-#define TOR_TORERR_H
-
-#include "common/compat_compiler.h"
-
-/* The raw_assert...() variants are for use within code that can't call
- * tor_assertion_failed_() because of call circularity issues. */
-#define raw_assert(expr) STMT_BEGIN \
- if (!(expr)) { \
- tor_raw_assertion_failed_msg_(__FILE__, __LINE__, #expr, NULL); \
- abort(); \
- } \
- STMT_END
-#define raw_assert_unreached(expr) raw_assert(0)
-#define raw_assert_unreached_msg(msg) STMT_BEGIN \
- tor_raw_assertion_failed_msg_(__FILE__, __LINE__, "0", (msg)); \
- abort(); \
- STMT_END
-
-void tor_raw_assertion_failed_msg_(const char *file, int line,
- const char *expr,
- const char *msg);
-
-/** Maximum number of fds that will get notifications if we crash */
-#define TOR_SIGSAFE_LOG_MAX_FDS 8
-
-void tor_log_err_sigsafe(const char *m, ...);
-int tor_log_get_sigsafe_err_fds(const int **out);
-void tor_log_set_sigsafe_err_fds(const int *fds, int n);
-void tor_log_sigsafe_err_set_granularity(int ms);
-
-int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
-int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
-
-#endif /* !defined(TOR_TORLOG_H) */