[tor-commits] [tor/master] Make unix sockets work with the linux seccomp2 sandbox again

nickm at torproject.org nickm at torproject.org
Tue Mar 22 14:10:39 UTC 2016


commit dd7c99961774c19c6042100e660104c687ad6e22
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Mar 14 14:07:02 2016 -0400

    Make unix sockets work with the linux seccomp2 sandbox again
    
    I didn't want to grant blanket permissions for chmod() and chown(),
    so here's what I had to do:
       * Grant open() on all parent directories of a unix socket
       * Write code to allow chmod() and chown() on a given file only.
       * Grant chmod() and chown() on the unix socket.
---
 src/common/sandbox.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/common/sandbox.h |  3 ++
 src/or/connection.c  |  6 ++--
 src/or/main.c        | 14 +++++++++
 4 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index 4e765b7..586d5fa 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001 Matej Pfajfar.
+ /* Copyright (c) 2001 Matej Pfajfar.
  * Copyright (c) 2001-2004, Roger Dingledine.
  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  * Copyright (c) 2007-2016, The Tor Project, Inc. */
@@ -439,6 +439,56 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 }
 
 static int
+sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+  int rc;
+  sandbox_cfg_t *elem = NULL;
+
+  // for each dynamic parameter filters
+  for (elem = filter; elem != NULL; elem = elem->next) {
+    smp_param_t *param = elem->param;
+
+    if (param != NULL && param->prot == 1 && param->syscall
+        == SCMP_SYS(chmod)) {
+      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
+            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
+      if (rc != 0) {
+        log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+            "libseccomp error %d", rc);
+        return rc;
+      }
+    }
+  }
+
+  return 0;
+}
+
+static int
+sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+  int rc;
+  sandbox_cfg_t *elem = NULL;
+
+  // for each dynamic parameter filters
+  for (elem = filter; elem != NULL; elem = elem->next) {
+    smp_param_t *param = elem->param;
+
+    if (param != NULL && param->prot == 1 && param->syscall
+        == SCMP_SYS(chown)) {
+      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
+            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
+      if (rc != 0) {
+        log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+            "libseccomp error %d", rc);
+        return rc;
+      }
+    }
+  }
+
+  return 0;
+}
+
+static int
 sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 {
   int rc;
@@ -971,6 +1021,8 @@ static sandbox_filter_func_t filter_func[] = {
 #ifdef __NR_mmap2
     sb_mmap2,
 #endif
+    sb_chown,
+    sb_chmod,
     sb_open,
     sb_openat,
     sb__sysctl,
@@ -1247,6 +1299,40 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
 }
 
 int
+sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
+{
+  sandbox_cfg_t *elem = NULL;
+
+  elem = new_element(SCMP_SYS(chmod), file);
+  if (!elem) {
+    log_err(LD_BUG,"(Sandbox) failed to register parameter!");
+    return -1;
+  }
+
+  elem->next = *cfg;
+  *cfg = elem;
+
+  return 0;
+}
+
+int
+sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
+{
+  sandbox_cfg_t *elem = NULL;
+
+  elem = new_element(SCMP_SYS(chown), file);
+  if (!elem) {
+    log_err(LD_BUG,"(Sandbox) failed to register parameter!");
+    return -1;
+  }
+
+  elem->next = *cfg;
+  *cfg = elem;
+
+  return 0;
+}
+
+int
 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
 {
   sandbox_cfg_t *elem = NULL;
diff --git a/src/common/sandbox.h b/src/common/sandbox.h
index b4cc9f7..4918ad0 100644
--- a/src/common/sandbox.h
+++ b/src/common/sandbox.h
@@ -149,6 +149,9 @@ sandbox_cfg_t * sandbox_cfg_new(void);
  */
 int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file);
 
+int sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file);
+int sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file);
+
 /**DOCDOC*/
 int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2);
 
diff --git a/src/or/connection.c b/src/or/connection.c
index 2c135ca..19e4b41 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -49,6 +49,7 @@
 #include "routerlist.h"
 #include "transports.h"
 #include "routerparse.h"
+#include "sandbox.h"
 #include "transports.h"
 
 #ifdef USE_BUFFEREVENTS
@@ -1291,7 +1292,8 @@ connection_listener_new(const struct sockaddr *listensockaddr,
       } else if (fstat(s, &st) == 0 &&
                  st.st_uid == pw->pw_uid && st.st_gid == pw->pw_gid) {
         /* No change needed */
-      } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) {
+      } else if (chown(sandbox_intern_string(address),
+                       pw->pw_uid, pw->pw_gid) < 0) {
         log_warn(LD_NET,"Unable to chown() %s socket: %s.",
                  address, strerror(errno));
         goto err;
@@ -1317,7 +1319,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
        * platforms. */
       if (fstat(s, &st) == 0 && (st.st_mode & 0777) == mode) {
         /* no change needed */
-      } else if (chmod(address, mode) < 0) {
+      } else if (chmod(sandbox_intern_string(address), mode) < 0) {
         log_warn(LD_FS,"Unable to make %s %s.", address, status);
         goto err;
       }
diff --git a/src/or/main.c b/src/or/main.c
index cfd1169..5ba97a5 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -3474,6 +3474,20 @@ sandbox_init_filter(void)
     }
   }
 
+  SMARTLIST_FOREACH_BEGIN(get_configured_ports(), port_cfg_t *, port) {
+    if (!port->is_unix_addr)
+      continue;
+    /* When we open an AF_UNIX address, we want permission to open the
+     * directory that holds it. */
+    char *dirname = tor_strdup(port->unix_addr);
+    if (get_parent_directory(dirname) == 0) {
+      OPEN(dirname);
+    }
+    tor_free(dirname);
+    sandbox_cfg_allow_chmod_filename(&cfg, tor_strdup(port->unix_addr));
+    sandbox_cfg_allow_chown_filename(&cfg, tor_strdup(port->unix_addr));
+  } SMARTLIST_FOREACH_END(port);
+
   if (options->DirPortFrontPage) {
     sandbox_cfg_allow_open_filename(&cfg,
                                     tor_strdup(options->DirPortFrontPage));





More information about the tor-commits mailing list