]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
sandbox: Allow use with fragile hardening
authorSimon South <simon@simonsouth.net>
Fri, 24 Sep 2021 18:08:58 +0000 (14:08 -0400)
committerSimon South <simon@simonsouth.net>
Tue, 28 Sep 2021 15:06:50 +0000 (11:06 -0400)
When building with --enable-fragile-hardening, add or relax Linux
seccomp rules to allow AddressSanitizer to execute normally if the
process terminates with the sandbox active.

Further resolves issue 11477.

changes/issue11477 [new file with mode: 0644]
src/app/main/main.c
src/lib/sandbox/sandbox.c

diff --git a/changes/issue11477 b/changes/issue11477
new file mode 100644 (file)
index 0000000..bb5d9e4
--- /dev/null
@@ -0,0 +1,8 @@
+  o Minor bugfixes (fragile-hardening, sandbox):
+    - When building with --enable-fragile-hardening, add or relax Linux
+      seccomp rules to allow AddressSanitizer to execute normally if the
+      process terminates with the sandbox active. This has the side
+      effect of disabling the filtering of file- and directory-open
+      requests on most systems and dilutes the effectiveness of the
+      sandbox overall, as a wider range of system calls must be
+      permitted. Fixes bug 11477; bugfix on 0.2.5.4-alpha.
index 89564490e6668a9c6d2925ab366bb4dde74fe2e7..0959b0db71efd29099412d43b3d301263557a630 100644 (file)
@@ -1343,6 +1343,13 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
   pubsub_connect();
 
   if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) {
+#ifdef ENABLE_FRAGILE_HARDENING
+    log_warn(LD_CONFIG, "Sandbox is enabled but this Tor was built using "
+             "fragile compiler hardening. The sandbox may be unable to filter "
+             "requests to open files and directories and its overall "
+             "effectiveness will be reduced.");
+#endif
+
     sandbox_cfg_t* cfg = sandbox_init_filter();
 
     if (sandbox_init(cfg)) {
index 02222e5a1c31e4912f40ed39cc098b4456222316..a78e4a7ac7392f6efd608f6e3182e0ebcc1f0565 100644 (file)
 #include <linux/futex.h>
 #include <sys/file.h>
 
+#ifdef ENABLE_FRAGILE_HARDENING
+#include <sys/ptrace.h>
+#endif
+
 #include <stdarg.h>
 #include <seccomp.h>
 #include <signal.h>
@@ -191,6 +195,9 @@ static int filter_nopar_gen[] = {
     SCMP_SYS(getgid32),
 #endif
     SCMP_SYS(getpid),
+#ifdef ENABLE_FRAGILE_HARDENING
+    SCMP_SYS(getppid),
+#endif
 #ifdef __NR_getrlimit
     SCMP_SYS(getrlimit),
 #endif
@@ -532,6 +539,24 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
   int use_openat = libc_uses_openat_for_open();
 
+#ifdef ENABLE_FRAGILE_HARDENING
+  /* AddressSanitizer uses the "open" syscall to access information about the
+   * running process via the filesystem, so that call must be allowed without
+   * restriction or the sanitizer will be unable to execute normally when the
+   * process terminates. */
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
+  if (rc != 0) {
+    log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+        "libseccomp error %d", rc);
+    return rc;
+  }
+
+  /* If glibc also uses only the "open" syscall to open files on this system
+   * there is no need to consider any additional rules. */
+  if (!use_openat)
+    return 0;
+#endif
+
   // for each dynamic parameter filters
   for (elem = filter; elem != NULL; elem = elem->next) {
     smp_param_t *param = elem->param;
@@ -687,6 +712,34 @@ sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   return 0;
 }
 
+#ifdef ENABLE_FRAGILE_HARDENING
+/**
+ * Function responsible for setting up the ptrace syscall for
+ * the seccomp filter sandbox.
+ */
+static int
+sb_ptrace(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+  int rc;
+  pid_t pid = getpid();
+  (void) filter;
+
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+      SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_ATTACH),
+      SCMP_CMP(1, SCMP_CMP_EQ, pid));
+  if (rc)
+    return rc;
+
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+      SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
+      SCMP_CMP(1, SCMP_CMP_EQ, pid));
+  if (rc)
+    return rc;
+
+  return 0;
+}
+#endif
+
 /**
  * Function responsible for setting up the socket syscall for
  * the seccomp filter sandbox.
@@ -1009,6 +1062,18 @@ sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
+#ifdef ENABLE_FRAGILE_HARDENING
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
+      SCMP_CMP(0, SCMP_CMP_EQ, PR_GET_DUMPABLE));
+  if (rc)
+    return rc;
+
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
+      SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PTRACER));
+  if (rc)
+    return rc;
+#endif
+
   rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
       SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
   if (rc)
@@ -1053,6 +1118,13 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
+#ifdef ENABLE_FRAGILE_HARDENING
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
+      SCMP_CMP(0, SCMP_CMP_EQ, SIG_BLOCK));
+  if (rc)
+    return rc;
+#endif
+
   rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
       SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
   if (rc)
@@ -1202,6 +1274,9 @@ static sandbox_filter_func_t filter_func[] = {
     sb_open,
     sb_openat,
     sb_opendir,
+#ifdef ENABLE_FRAGILE_HARDENING
+    sb_ptrace,
+#endif
     sb_rename,
 #ifdef __NR_fcntl64
     sb_fcntl64,