Commit 125c8e54 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Merge remote-tracking branch 'public/bug11465'

parents 03e0c7e3 bd83d0ed
Loading
Loading
Loading
Loading

changes/bug11465

0 → 100644
+9 −0
Original line number Diff line number Diff line
  o Minor features:
    - When the Linux syscall sandbox finds an illegal system call, it
      now tries to log a stack trace before exiting. Resolves ticket
      11465.

  o Minor bugfixes:
    - Using the Linux syscall sandbox no longer prevents stack-trace
      logging on crashes or errors. Fixes part 11465; bugfix on
      0.2.5.1-alpha.
+16 −2
Original line number Diff line number Diff line
@@ -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;
}

+6 −0
Original line number Diff line number Diff line
@@ -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
+36 −0
Original line number Diff line number Diff line
@@ -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.*/
@@ -119,6 +130,7 @@ static int filter_nopar_gen[] = {
    SCMP_SYS(stat),
    SCMP_SYS(uname),
    SCMP_SYS(write),
    SCMP_SYS(writev),
    SCMP_SYS(exit_group),
    SCMP_SYS(exit),

@@ -1307,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
@@ -1318,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)
@@ -1328,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