[tor-commits] [tor/master] Log a backtrace when the sandbox finds a failure

nickm at torproject.org nickm at torproject.org
Wed Apr 16 00:55:49 UTC 2014


commit cc9e86db61e2ffb6c54b09e8c41e8fdad50b3ef3
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Apr 10 15:44:52 2014 -0400

    Log a backtrace when the sandbox finds a failure
    
    This involves some duplicate code between backtrace.c and sandbox.c,
    but I don't see a way around it: calling more functions would mean
    adding more steps to our call stack, and running clean_backtrace()
    against the wrong point on the stack.
---
 src/common/backtrace.c |   18 ++++++++++++++++--
 src/common/backtrace.h |    6 ++++++
 src/common/sandbox.c   |   35 +++++++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/common/backtrace.c b/src/common/backtrace.c
index 239c657..3a073a8 100644
--- a/src/common/backtrace.c
+++ b/src/common/backtrace.c
@@ -5,7 +5,6 @@
 #define _GNU_SOURCE 1
 
 #include "orconfig.h"
-#include "backtrace.h"
 #include "compat.h"
 #include "util.h"
 #include "torlog.h"
@@ -31,6 +30,9 @@
 #include <ucontext.h>
 #endif
 
+#define EXPOSE_CLEAN_BACKTRACE
+#include "backtrace.h"
+
 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
   defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
 #define USE_BACKTRACE
@@ -59,7 +61,7 @@ static tor_mutex_t cb_buf_mutex;
  * onto the stack.  Fortunately, we usually have the program counter in the
  * ucontext_t structure.
  */
-static void
+void
 clean_backtrace(void **stack, int depth, const ucontext_t *ctx)
 {
 #ifdef PC_FROM_UCONTEXT
@@ -165,6 +167,18 @@ install_bt_handler(void)
       rv = -1;
     }
   }
+
+  {
+    /* 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;
+    int depth = backtrace(cb_buf, MAX_DEPTH);
+    symbols = backtrace_symbols(cb_buf, depth);
+    if (symbols)
+      free(symbols);
+  }
+
   return rv;
 }
 
diff --git a/src/common/backtrace.h b/src/common/backtrace.h
index 765436f..b1df281 100644
--- a/src/common/backtrace.h
+++ b/src/common/backtrace.h
@@ -4,9 +4,15 @@
 #ifndef TOR_BACKTRACE_H
 #define TOR_BACKTRACE_H
 
+#include "orconfig.h"
+
 void log_backtrace(int severity, int domain, const char *msg);
 int configure_backtrace_handler(const char *tor_version);
 void clean_up_backtrace_handler(void);
 
+#ifdef EXPOSE_CLEAN_BACKTRACE
+void clean_backtrace(void **stack, int depth, const ucontext_t *ctx);
+#endif
+
 #endif
 
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index 0a7a129..0548f3e 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -56,6 +56,17 @@
 #include <time.h>
 #include <poll.h>
 
+#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
+  defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
+#define USE_BACKTRACE
+#define EXPOSE_CLEAN_BACKTRACE
+#include "backtrace.h"
+#endif
+
+#ifdef USE_BACKTRACE
+#include <execinfo.h>
+#endif
+
 /**Determines if at least one sandbox is active.*/
 static int sandbox_active = 0;
 /** Holds the parameter list configuration for the sandbox.*/
@@ -1308,6 +1319,11 @@ install_syscall_filter(sandbox_cfg_t* cfg)
   return (rc < 0 ? -rc : rc);
 }
 
+#ifdef USE_BACKTRACE
+#define MAX_DEPTH 256
+static void *syscall_cb_buf[MAX_DEPTH];
+#endif
+
 /**
  * Function called when a SIGSYS is caught by the application. It notifies the
  * user that an error has occurred and either terminates or allows the
@@ -1319,6 +1335,12 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context)
   ucontext_t *ctx = (ucontext_t *) (void_context);
   char number[32];
   int syscall;
+#ifdef USE_BACKTRACE
+  int depth;
+  int n_fds, i;
+  const int *fds = NULL;
+#endif
+
   (void) nr;
 
   if (info->si_code != SYS_SECCOMP)
@@ -1329,12 +1351,25 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context)
 
   syscall = (int) ctx->uc_mcontext.gregs[REG_SYSCALL];
 
+#ifdef USE_BACKTRACE
+  depth = backtrace(syscall_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(syscall_cb_buf, depth, ctx);
+#endif
+
   format_dec_number_sigsafe(syscall, number, sizeof(number));
   tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
                       number,
                       ")\n",
                       NULL);
 
+#ifdef USE_BACKTRACE
+  n_fds = tor_log_get_sigsafe_err_fds(&fds);
+  for (i=0; i < n_fds; ++i)
+    backtrace_symbols_fd(syscall_cb_buf, depth, fds[i]);
+#endif
+
 #if defined(DEBUGGING_CLOSE)
   _exit(1);
 #endif // DEBUGGING_CLOSE





More information about the tor-commits mailing list