Browse Source

Merge remote-tracking branch 'public/sandbox_fixes_rebased_2'

Nick Mathewson 10 years ago
parent
commit
4367cbd71b

+ 13 - 0
changes/sandbox_fixes_11351

@@ -0,0 +1,13 @@
+  o Major features:
+    - Refinements and improvements to the Linux seccomp2 sandbox code:
+      the sandbox can now run a test network for multiple hours without
+      crashing. (Previous crash reasons included: reseeding the OpenSSL PRNG,
+      seeding the Libevent PRNG, using the wrong combination of CLOEXEC and
+      NONBLOCK at the same place and time, having server keys, being an
+      authority, receiving a HUP, or using IPv6.) The sandbox is still
+      experimental, and more bugs will probably turn up. To try it,
+      enable "Sandbox 1" on a Linux host.
+
+    - Strengthen the Linux seccomp2 sandbox code: the sandbox can now
+      test the arguments for rename(), and blocks _sysctl() entirely.
+

+ 1 - 0
configure.ac

@@ -435,6 +435,7 @@ AC_CHECK_FUNCS([event_get_version \
                 event_set_log_callback \
                 evdns_set_outgoing_bind_address \
                 evutil_secure_rng_set_urandom_device_file \
+                evutil_secure_rng_init \
                 event_base_loopexit])
 AC_CHECK_MEMBERS([struct event.min_heap_idx], , ,
 [#include <event.h>

+ 12 - 2
src/common/compat.c

@@ -144,6 +144,7 @@ tor_open_cloexec(const char *path, int flags, unsigned mode)
     return -1;
 #endif
 
+  log_debug(LD_FS, "Opening %s with flags %x", path, flags);
   fd = open(path, flags, mode);
 #ifdef FD_CLOEXEC
   if (fd >= 0) {
@@ -175,6 +176,15 @@ tor_fopen_cloexec(const char *path, const char *mode)
   return result;
 }
 
+/** As rename(), but work correctly with the sandbox. */
+int
+tor_rename(const char *path_old, const char *path_new)
+{
+  log_debug(LD_FS, "Renaming %s to %s", path_old, path_new);
+  return rename(sandbox_intern_string(path_old),
+                sandbox_intern_string(path_new));
+}
+
 #if defined(HAVE_SYS_MMAN_H) || defined(RUNNING_DOXYGEN)
 /** Try to create a memory mapping for <b>filename</b> and return it.  On
  * failure, return NULL.  Sets errno properly, using ERANGE to mean
@@ -799,7 +809,7 @@ int
 replace_file(const char *from, const char *to)
 {
 #ifndef _WIN32
-  return rename(from,to);
+  return tor_rename(from, to);
 #else
   switch (file_status(to))
     {
@@ -814,7 +824,7 @@ replace_file(const char *from, const char *to)
       errno = EISDIR;
       return -1;
     }
-  return rename(from,to);
+  return tor_rename(from,to);
 #endif
 }
 

+ 1 - 0
src/common/compat.h

@@ -410,6 +410,7 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
 /* ===== File compatibility */
 int tor_open_cloexec(const char *path, int flags, unsigned mode);
 FILE *tor_fopen_cloexec(const char *path, const char *mode);
+int tor_rename(const char *path_old, const char *path_new);
 
 int replace_file(const char *from, const char *to);
 int touch_file(const char *fname);

+ 19 - 0
src/common/compat_libevent.c

@@ -13,6 +13,8 @@
 #include "compat.h"
 #include "compat_libevent.h"
 
+#include "crypto.h"
+
 #include "util.h"
 #include "torlog.h"
 
@@ -626,6 +628,23 @@ tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
 }
 #endif
 
+int
+tor_init_libevent_rng(void)
+{
+  int rv = 0;
+#ifdef HAVE_EVUTIL_SECURE_RNG_INIT
+  char buf[256];
+  if (evutil_secure_rng_init() < 0) {
+    rv = -1;
+  }
+  /* Older libevent -- manually initialize the RNG */
+  crypto_rand(buf, 32);
+  evutil_secure_rng_add_bytes(buf, 32);
+  evutil_secure_rng_get_bytes(buf, sizeof(buf));
+#endif
+  return rv;
+}
+
 #if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,1,1) \
   && !defined(TOR_UNIT_TESTS)
 void

+ 2 - 0
src/common/compat_libevent.h

@@ -89,6 +89,8 @@ int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
                                    struct bufferevent_rate_limit_group *g);
 #endif
 
+int tor_init_libevent_rng(void);
+
 void tor_gettimeofday_cached(struct timeval *tv);
 void tor_gettimeofday_cache_clear(void);
 #ifdef TOR_UNIT_TESTS

+ 1 - 0
src/common/crypto.c

@@ -2471,6 +2471,7 @@ crypto_strongest_rand(uint8_t *out, size_t out_len)
   return 0;
 #else
   for (i = 0; filenames[i]; ++i) {
+    log_debug(LD_FS, "Opening %s for entropy", filenames[i]);
     fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
     if (fd<0) continue;
     log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);

+ 37 - 0
src/common/gen_linux_syscalls.pl

@@ -0,0 +1,37 @@
+#!/usr/bin/perl -w
+
+use strict;
+my %syscalls = ();
+
+while (<>) {
+    if (/^#define (__NR_\w+) /) {
+	$syscalls{$1} = 1;
+    }
+}
+
+print <<EOL;
+/* Automatically generated with
+        gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h
+   Do not edit.
+ */
+static const struct {
+  int syscall_num; const char *syscall_name;
+} SYSCALLS_BY_NUMBER[] = {
+EOL
+
+for my $k (sort keys %syscalls) {
+    my $name = $k;
+    $name =~ s/^__NR_//;
+    print <<EOL;
+#ifdef $k
+  { $k, "$name" },
+#endif
+EOL
+
+}
+
+print <<EOL
+  {0, NULL}
+};
+
+EOL

+ 1 - 0
src/common/include.am

@@ -103,6 +103,7 @@ COMMONHEADERS = \
   src/common/di_ops.h				\
   src/common/memarea.h				\
   src/common/mempool.h				\
+  src/common/linux_syscalls.inc			\
   src/common/procmon.h				\
   src/common/sandbox.h				\
   src/common/testsupport.h			\

+ 1153 - 0
src/common/linux_syscalls.inc

@@ -0,0 +1,1153 @@
+/* Automatically generated with
+        gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h
+   Do not edit.
+ */
+static const struct {
+  int syscall_num; const char *syscall_name;
+} SYSCALLS_BY_NUMBER[] = {
+#ifdef __NR__llseek
+  { __NR__llseek, "_llseek" },
+#endif
+#ifdef __NR__newselect
+  { __NR__newselect, "_newselect" },
+#endif
+#ifdef __NR__sysctl
+  { __NR__sysctl, "_sysctl" },
+#endif
+#ifdef __NR_accept
+  { __NR_accept, "accept" },
+#endif
+#ifdef __NR_accept4
+  { __NR_accept4, "accept4" },
+#endif
+#ifdef __NR_access
+  { __NR_access, "access" },
+#endif
+#ifdef __NR_acct
+  { __NR_acct, "acct" },
+#endif
+#ifdef __NR_add_key
+  { __NR_add_key, "add_key" },
+#endif
+#ifdef __NR_adjtimex
+  { __NR_adjtimex, "adjtimex" },
+#endif
+#ifdef __NR_afs_syscall
+  { __NR_afs_syscall, "afs_syscall" },
+#endif
+#ifdef __NR_alarm
+  { __NR_alarm, "alarm" },
+#endif
+#ifdef __NR_arch_prctl
+  { __NR_arch_prctl, "arch_prctl" },
+#endif
+#ifdef __NR_bdflush
+  { __NR_bdflush, "bdflush" },
+#endif
+#ifdef __NR_bind
+  { __NR_bind, "bind" },
+#endif
+#ifdef __NR_break
+  { __NR_break, "break" },
+#endif
+#ifdef __NR_brk
+  { __NR_brk, "brk" },
+#endif
+#ifdef __NR_capget
+  { __NR_capget, "capget" },
+#endif
+#ifdef __NR_capset
+  { __NR_capset, "capset" },
+#endif
+#ifdef __NR_chdir
+  { __NR_chdir, "chdir" },
+#endif
+#ifdef __NR_chmod
+  { __NR_chmod, "chmod" },
+#endif
+#ifdef __NR_chown
+  { __NR_chown, "chown" },
+#endif
+#ifdef __NR_chown32
+  { __NR_chown32, "chown32" },
+#endif
+#ifdef __NR_chroot
+  { __NR_chroot, "chroot" },
+#endif
+#ifdef __NR_clock_adjtime
+  { __NR_clock_adjtime, "clock_adjtime" },
+#endif
+#ifdef __NR_clock_getres
+  { __NR_clock_getres, "clock_getres" },
+#endif
+#ifdef __NR_clock_gettime
+  { __NR_clock_gettime, "clock_gettime" },
+#endif
+#ifdef __NR_clock_nanosleep
+  { __NR_clock_nanosleep, "clock_nanosleep" },
+#endif
+#ifdef __NR_clock_settime
+  { __NR_clock_settime, "clock_settime" },
+#endif
+#ifdef __NR_clone
+  { __NR_clone, "clone" },
+#endif
+#ifdef __NR_close
+  { __NR_close, "close" },
+#endif
+#ifdef __NR_connect
+  { __NR_connect, "connect" },
+#endif
+#ifdef __NR_creat
+  { __NR_creat, "creat" },
+#endif
+#ifdef __NR_create_module
+  { __NR_create_module, "create_module" },
+#endif
+#ifdef __NR_delete_module
+  { __NR_delete_module, "delete_module" },
+#endif
+#ifdef __NR_dup
+  { __NR_dup, "dup" },
+#endif
+#ifdef __NR_dup2
+  { __NR_dup2, "dup2" },
+#endif
+#ifdef __NR_dup3
+  { __NR_dup3, "dup3" },
+#endif
+#ifdef __NR_epoll_create
+  { __NR_epoll_create, "epoll_create" },
+#endif
+#ifdef __NR_epoll_create1
+  { __NR_epoll_create1, "epoll_create1" },
+#endif
+#ifdef __NR_epoll_ctl
+  { __NR_epoll_ctl, "epoll_ctl" },
+#endif
+#ifdef __NR_epoll_ctl_old
+  { __NR_epoll_ctl_old, "epoll_ctl_old" },
+#endif
+#ifdef __NR_epoll_pwait
+  { __NR_epoll_pwait, "epoll_pwait" },
+#endif
+#ifdef __NR_epoll_wait
+  { __NR_epoll_wait, "epoll_wait" },
+#endif
+#ifdef __NR_epoll_wait_old
+  { __NR_epoll_wait_old, "epoll_wait_old" },
+#endif
+#ifdef __NR_eventfd
+  { __NR_eventfd, "eventfd" },
+#endif
+#ifdef __NR_eventfd2
+  { __NR_eventfd2, "eventfd2" },
+#endif
+#ifdef __NR_execve
+  { __NR_execve, "execve" },
+#endif
+#ifdef __NR_exit
+  { __NR_exit, "exit" },
+#endif
+#ifdef __NR_exit_group
+  { __NR_exit_group, "exit_group" },
+#endif
+#ifdef __NR_faccessat
+  { __NR_faccessat, "faccessat" },
+#endif
+#ifdef __NR_fadvise64
+  { __NR_fadvise64, "fadvise64" },
+#endif
+#ifdef __NR_fadvise64_64
+  { __NR_fadvise64_64, "fadvise64_64" },
+#endif
+#ifdef __NR_fallocate
+  { __NR_fallocate, "fallocate" },
+#endif
+#ifdef __NR_fanotify_init
+  { __NR_fanotify_init, "fanotify_init" },
+#endif
+#ifdef __NR_fanotify_mark
+  { __NR_fanotify_mark, "fanotify_mark" },
+#endif
+#ifdef __NR_fchdir
+  { __NR_fchdir, "fchdir" },
+#endif
+#ifdef __NR_fchmod
+  { __NR_fchmod, "fchmod" },
+#endif
+#ifdef __NR_fchmodat
+  { __NR_fchmodat, "fchmodat" },
+#endif
+#ifdef __NR_fchown
+  { __NR_fchown, "fchown" },
+#endif
+#ifdef __NR_fchown32
+  { __NR_fchown32, "fchown32" },
+#endif
+#ifdef __NR_fchownat
+  { __NR_fchownat, "fchownat" },
+#endif
+#ifdef __NR_fcntl
+  { __NR_fcntl, "fcntl" },
+#endif
+#ifdef __NR_fcntl64
+  { __NR_fcntl64, "fcntl64" },
+#endif
+#ifdef __NR_fdatasync
+  { __NR_fdatasync, "fdatasync" },
+#endif
+#ifdef __NR_fgetxattr
+  { __NR_fgetxattr, "fgetxattr" },
+#endif
+#ifdef __NR_finit_module
+  { __NR_finit_module, "finit_module" },
+#endif
+#ifdef __NR_flistxattr
+  { __NR_flistxattr, "flistxattr" },
+#endif
+#ifdef __NR_flock
+  { __NR_flock, "flock" },
+#endif
+#ifdef __NR_fork
+  { __NR_fork, "fork" },
+#endif
+#ifdef __NR_fremovexattr
+  { __NR_fremovexattr, "fremovexattr" },
+#endif
+#ifdef __NR_fsetxattr
+  { __NR_fsetxattr, "fsetxattr" },
+#endif
+#ifdef __NR_fstat
+  { __NR_fstat, "fstat" },
+#endif
+#ifdef __NR_fstat64
+  { __NR_fstat64, "fstat64" },
+#endif
+#ifdef __NR_fstatat64
+  { __NR_fstatat64, "fstatat64" },
+#endif
+#ifdef __NR_fstatfs
+  { __NR_fstatfs, "fstatfs" },
+#endif
+#ifdef __NR_fstatfs64
+  { __NR_fstatfs64, "fstatfs64" },
+#endif
+#ifdef __NR_fsync
+  { __NR_fsync, "fsync" },
+#endif
+#ifdef __NR_ftime
+  { __NR_ftime, "ftime" },
+#endif
+#ifdef __NR_ftruncate
+  { __NR_ftruncate, "ftruncate" },
+#endif
+#ifdef __NR_ftruncate64
+  { __NR_ftruncate64, "ftruncate64" },
+#endif
+#ifdef __NR_futex
+  { __NR_futex, "futex" },
+#endif
+#ifdef __NR_futimesat
+  { __NR_futimesat, "futimesat" },
+#endif
+#ifdef __NR_get_kernel_syms
+  { __NR_get_kernel_syms, "get_kernel_syms" },
+#endif
+#ifdef __NR_get_mempolicy
+  { __NR_get_mempolicy, "get_mempolicy" },
+#endif
+#ifdef __NR_get_robust_list
+  { __NR_get_robust_list, "get_robust_list" },
+#endif
+#ifdef __NR_get_thread_area
+  { __NR_get_thread_area, "get_thread_area" },
+#endif
+#ifdef __NR_getcpu
+  { __NR_getcpu, "getcpu" },
+#endif
+#ifdef __NR_getcwd
+  { __NR_getcwd, "getcwd" },
+#endif
+#ifdef __NR_getdents
+  { __NR_getdents, "getdents" },
+#endif
+#ifdef __NR_getdents64
+  { __NR_getdents64, "getdents64" },
+#endif
+#ifdef __NR_getegid
+  { __NR_getegid, "getegid" },
+#endif
+#ifdef __NR_getegid32
+  { __NR_getegid32, "getegid32" },
+#endif
+#ifdef __NR_geteuid
+  { __NR_geteuid, "geteuid" },
+#endif
+#ifdef __NR_geteuid32
+  { __NR_geteuid32, "geteuid32" },
+#endif
+#ifdef __NR_getgid
+  { __NR_getgid, "getgid" },
+#endif
+#ifdef __NR_getgid32
+  { __NR_getgid32, "getgid32" },
+#endif
+#ifdef __NR_getgroups
+  { __NR_getgroups, "getgroups" },
+#endif
+#ifdef __NR_getgroups32
+  { __NR_getgroups32, "getgroups32" },
+#endif
+#ifdef __NR_getitimer
+  { __NR_getitimer, "getitimer" },
+#endif
+#ifdef __NR_getpeername
+  { __NR_getpeername, "getpeername" },
+#endif
+#ifdef __NR_getpgid
+  { __NR_getpgid, "getpgid" },
+#endif
+#ifdef __NR_getpgrp
+  { __NR_getpgrp, "getpgrp" },
+#endif
+#ifdef __NR_getpid
+  { __NR_getpid, "getpid" },
+#endif
+#ifdef __NR_getpmsg
+  { __NR_getpmsg, "getpmsg" },
+#endif
+#ifdef __NR_getppid
+  { __NR_getppid, "getppid" },
+#endif
+#ifdef __NR_getpriority
+  { __NR_getpriority, "getpriority" },
+#endif
+#ifdef __NR_getresgid
+  { __NR_getresgid, "getresgid" },
+#endif
+#ifdef __NR_getresgid32
+  { __NR_getresgid32, "getresgid32" },
+#endif
+#ifdef __NR_getresuid
+  { __NR_getresuid, "getresuid" },
+#endif
+#ifdef __NR_getresuid32
+  { __NR_getresuid32, "getresuid32" },
+#endif
+#ifdef __NR_getrlimit
+  { __NR_getrlimit, "getrlimit" },
+#endif
+#ifdef __NR_getrusage
+  { __NR_getrusage, "getrusage" },
+#endif
+#ifdef __NR_getsid
+  { __NR_getsid, "getsid" },
+#endif
+#ifdef __NR_getsockname
+  { __NR_getsockname, "getsockname" },
+#endif
+#ifdef __NR_getsockopt
+  { __NR_getsockopt, "getsockopt" },
+#endif
+#ifdef __NR_gettid
+  { __NR_gettid, "gettid" },
+#endif
+#ifdef __NR_gettimeofday
+  { __NR_gettimeofday, "gettimeofday" },
+#endif
+#ifdef __NR_getuid
+  { __NR_getuid, "getuid" },
+#endif
+#ifdef __NR_getuid32
+  { __NR_getuid32, "getuid32" },
+#endif
+#ifdef __NR_getxattr
+  { __NR_getxattr, "getxattr" },
+#endif
+#ifdef __NR_gtty
+  { __NR_gtty, "gtty" },
+#endif
+#ifdef __NR_idle
+  { __NR_idle, "idle" },
+#endif
+#ifdef __NR_init_module
+  { __NR_init_module, "init_module" },
+#endif
+#ifdef __NR_inotify_add_watch
+  { __NR_inotify_add_watch, "inotify_add_watch" },
+#endif
+#ifdef __NR_inotify_init
+  { __NR_inotify_init, "inotify_init" },
+#endif
+#ifdef __NR_inotify_init1
+  { __NR_inotify_init1, "inotify_init1" },
+#endif
+#ifdef __NR_inotify_rm_watch
+  { __NR_inotify_rm_watch, "inotify_rm_watch" },
+#endif
+#ifdef __NR_io_cancel
+  { __NR_io_cancel, "io_cancel" },
+#endif
+#ifdef __NR_io_destroy
+  { __NR_io_destroy, "io_destroy" },
+#endif
+#ifdef __NR_io_getevents
+  { __NR_io_getevents, "io_getevents" },
+#endif
+#ifdef __NR_io_setup
+  { __NR_io_setup, "io_setup" },
+#endif
+#ifdef __NR_io_submit
+  { __NR_io_submit, "io_submit" },
+#endif
+#ifdef __NR_ioctl
+  { __NR_ioctl, "ioctl" },
+#endif
+#ifdef __NR_ioperm
+  { __NR_ioperm, "ioperm" },
+#endif
+#ifdef __NR_iopl
+  { __NR_iopl, "iopl" },
+#endif
+#ifdef __NR_ioprio_get
+  { __NR_ioprio_get, "ioprio_get" },
+#endif
+#ifdef __NR_ioprio_set
+  { __NR_ioprio_set, "ioprio_set" },
+#endif
+#ifdef __NR_ipc
+  { __NR_ipc, "ipc" },
+#endif
+#ifdef __NR_kcmp
+  { __NR_kcmp, "kcmp" },
+#endif
+#ifdef __NR_kexec_load
+  { __NR_kexec_load, "kexec_load" },
+#endif
+#ifdef __NR_keyctl
+  { __NR_keyctl, "keyctl" },
+#endif
+#ifdef __NR_kill
+  { __NR_kill, "kill" },
+#endif
+#ifdef __NR_lchown
+  { __NR_lchown, "lchown" },
+#endif
+#ifdef __NR_lchown32
+  { __NR_lchown32, "lchown32" },
+#endif
+#ifdef __NR_lgetxattr
+  { __NR_lgetxattr, "lgetxattr" },
+#endif
+#ifdef __NR_link
+  { __NR_link, "link" },
+#endif
+#ifdef __NR_linkat
+  { __NR_linkat, "linkat" },
+#endif
+#ifdef __NR_listen
+  { __NR_listen, "listen" },
+#endif
+#ifdef __NR_listxattr
+  { __NR_listxattr, "listxattr" },
+#endif
+#ifdef __NR_llistxattr
+  { __NR_llistxattr, "llistxattr" },
+#endif
+#ifdef __NR_lock
+  { __NR_lock, "lock" },
+#endif
+#ifdef __NR_lookup_dcookie
+  { __NR_lookup_dcookie, "lookup_dcookie" },
+#endif
+#ifdef __NR_lremovexattr
+  { __NR_lremovexattr, "lremovexattr" },
+#endif
+#ifdef __NR_lseek
+  { __NR_lseek, "lseek" },
+#endif
+#ifdef __NR_lsetxattr
+  { __NR_lsetxattr, "lsetxattr" },
+#endif
+#ifdef __NR_lstat
+  { __NR_lstat, "lstat" },
+#endif
+#ifdef __NR_lstat64
+  { __NR_lstat64, "lstat64" },
+#endif
+#ifdef __NR_madvise
+  { __NR_madvise, "madvise" },
+#endif
+#ifdef __NR_mbind
+  { __NR_mbind, "mbind" },
+#endif
+#ifdef __NR_migrate_pages
+  { __NR_migrate_pages, "migrate_pages" },
+#endif
+#ifdef __NR_mincore
+  { __NR_mincore, "mincore" },
+#endif
+#ifdef __NR_mkdir
+  { __NR_mkdir, "mkdir" },
+#endif
+#ifdef __NR_mkdirat
+  { __NR_mkdirat, "mkdirat" },
+#endif
+#ifdef __NR_mknod
+  { __NR_mknod, "mknod" },
+#endif
+#ifdef __NR_mknodat
+  { __NR_mknodat, "mknodat" },
+#endif
+#ifdef __NR_mlock
+  { __NR_mlock, "mlock" },
+#endif
+#ifdef __NR_mlockall
+  { __NR_mlockall, "mlockall" },
+#endif
+#ifdef __NR_mmap
+  { __NR_mmap, "mmap" },
+#endif
+#ifdef __NR_mmap2
+  { __NR_mmap2, "mmap2" },
+#endif
+#ifdef __NR_modify_ldt
+  { __NR_modify_ldt, "modify_ldt" },
+#endif
+#ifdef __NR_mount
+  { __NR_mount, "mount" },
+#endif
+#ifdef __NR_move_pages
+  { __NR_move_pages, "move_pages" },
+#endif
+#ifdef __NR_mprotect
+  { __NR_mprotect, "mprotect" },
+#endif
+#ifdef __NR_mpx
+  { __NR_mpx, "mpx" },
+#endif
+#ifdef __NR_mq_getsetattr
+  { __NR_mq_getsetattr, "mq_getsetattr" },
+#endif
+#ifdef __NR_mq_notify
+  { __NR_mq_notify, "mq_notify" },
+#endif
+#ifdef __NR_mq_open
+  { __NR_mq_open, "mq_open" },
+#endif
+#ifdef __NR_mq_timedreceive
+  { __NR_mq_timedreceive, "mq_timedreceive" },
+#endif
+#ifdef __NR_mq_timedsend
+  { __NR_mq_timedsend, "mq_timedsend" },
+#endif
+#ifdef __NR_mq_unlink
+  { __NR_mq_unlink, "mq_unlink" },
+#endif
+#ifdef __NR_mremap
+  { __NR_mremap, "mremap" },
+#endif
+#ifdef __NR_msgctl
+  { __NR_msgctl, "msgctl" },
+#endif
+#ifdef __NR_msgget
+  { __NR_msgget, "msgget" },
+#endif
+#ifdef __NR_msgrcv
+  { __NR_msgrcv, "msgrcv" },
+#endif
+#ifdef __NR_msgsnd
+  { __NR_msgsnd, "msgsnd" },
+#endif
+#ifdef __NR_msync
+  { __NR_msync, "msync" },
+#endif
+#ifdef __NR_munlock
+  { __NR_munlock, "munlock" },
+#endif
+#ifdef __NR_munlockall
+  { __NR_munlockall, "munlockall" },
+#endif
+#ifdef __NR_munmap
+  { __NR_munmap, "munmap" },
+#endif
+#ifdef __NR_name_to_handle_at
+  { __NR_name_to_handle_at, "name_to_handle_at" },
+#endif
+#ifdef __NR_nanosleep
+  { __NR_nanosleep, "nanosleep" },
+#endif
+#ifdef __NR_newfstatat
+  { __NR_newfstatat, "newfstatat" },
+#endif
+#ifdef __NR_nfsservctl
+  { __NR_nfsservctl, "nfsservctl" },
+#endif
+#ifdef __NR_nice
+  { __NR_nice, "nice" },
+#endif
+#ifdef __NR_oldfstat
+  { __NR_oldfstat, "oldfstat" },
+#endif
+#ifdef __NR_oldlstat
+  { __NR_oldlstat, "oldlstat" },
+#endif
+#ifdef __NR_oldolduname
+  { __NR_oldolduname, "oldolduname" },
+#endif
+#ifdef __NR_oldstat
+  { __NR_oldstat, "oldstat" },
+#endif
+#ifdef __NR_olduname
+  { __NR_olduname, "olduname" },
+#endif
+#ifdef __NR_open
+  { __NR_open, "open" },
+#endif
+#ifdef __NR_open_by_handle_at
+  { __NR_open_by_handle_at, "open_by_handle_at" },
+#endif
+#ifdef __NR_openat
+  { __NR_openat, "openat" },
+#endif
+#ifdef __NR_pause
+  { __NR_pause, "pause" },
+#endif
+#ifdef __NR_perf_event_open
+  { __NR_perf_event_open, "perf_event_open" },
+#endif
+#ifdef __NR_personality
+  { __NR_personality, "personality" },
+#endif
+#ifdef __NR_pipe
+  { __NR_pipe, "pipe" },
+#endif
+#ifdef __NR_pipe2
+  { __NR_pipe2, "pipe2" },
+#endif
+#ifdef __NR_pivot_root
+  { __NR_pivot_root, "pivot_root" },
+#endif
+#ifdef __NR_poll
+  { __NR_poll, "poll" },
+#endif
+#ifdef __NR_ppoll
+  { __NR_ppoll, "ppoll" },
+#endif
+#ifdef __NR_prctl
+  { __NR_prctl, "prctl" },
+#endif
+#ifdef __NR_pread64
+  { __NR_pread64, "pread64" },
+#endif
+#ifdef __NR_preadv
+  { __NR_preadv, "preadv" },
+#endif
+#ifdef __NR_prlimit64
+  { __NR_prlimit64, "prlimit64" },
+#endif
+#ifdef __NR_process_vm_readv
+  { __NR_process_vm_readv, "process_vm_readv" },
+#endif
+#ifdef __NR_process_vm_writev
+  { __NR_process_vm_writev, "process_vm_writev" },
+#endif
+#ifdef __NR_prof
+  { __NR_prof, "prof" },
+#endif
+#ifdef __NR_profil
+  { __NR_profil, "profil" },
+#endif
+#ifdef __NR_pselect6
+  { __NR_pselect6, "pselect6" },
+#endif
+#ifdef __NR_ptrace
+  { __NR_ptrace, "ptrace" },
+#endif
+#ifdef __NR_putpmsg
+  { __NR_putpmsg, "putpmsg" },
+#endif
+#ifdef __NR_pwrite64
+  { __NR_pwrite64, "pwrite64" },
+#endif
+#ifdef __NR_pwritev
+  { __NR_pwritev, "pwritev" },
+#endif
+#ifdef __NR_query_module
+  { __NR_query_module, "query_module" },
+#endif
+#ifdef __NR_quotactl
+  { __NR_quotactl, "quotactl" },
+#endif
+#ifdef __NR_read
+  { __NR_read, "read" },
+#endif
+#ifdef __NR_readahead
+  { __NR_readahead, "readahead" },
+#endif
+#ifdef __NR_readdir
+  { __NR_readdir, "readdir" },
+#endif
+#ifdef __NR_readlink
+  { __NR_readlink, "readlink" },
+#endif
+#ifdef __NR_readlinkat
+  { __NR_readlinkat, "readlinkat" },
+#endif
+#ifdef __NR_readv
+  { __NR_readv, "readv" },
+#endif
+#ifdef __NR_reboot
+  { __NR_reboot, "reboot" },
+#endif
+#ifdef __NR_recvfrom
+  { __NR_recvfrom, "recvfrom" },
+#endif
+#ifdef __NR_recvmmsg
+  { __NR_recvmmsg, "recvmmsg" },
+#endif
+#ifdef __NR_recvmsg
+  { __NR_recvmsg, "recvmsg" },
+#endif
+#ifdef __NR_remap_file_pages
+  { __NR_remap_file_pages, "remap_file_pages" },
+#endif
+#ifdef __NR_removexattr
+  { __NR_removexattr, "removexattr" },
+#endif
+#ifdef __NR_rename
+  { __NR_rename, "rename" },
+#endif
+#ifdef __NR_renameat
+  { __NR_renameat, "renameat" },
+#endif
+#ifdef __NR_request_key
+  { __NR_request_key, "request_key" },
+#endif
+#ifdef __NR_restart_syscall
+  { __NR_restart_syscall, "restart_syscall" },
+#endif
+#ifdef __NR_rmdir
+  { __NR_rmdir, "rmdir" },
+#endif
+#ifdef __NR_rt_sigaction
+  { __NR_rt_sigaction, "rt_sigaction" },
+#endif
+#ifdef __NR_rt_sigpending
+  { __NR_rt_sigpending, "rt_sigpending" },
+#endif
+#ifdef __NR_rt_sigprocmask
+  { __NR_rt_sigprocmask, "rt_sigprocmask" },
+#endif
+#ifdef __NR_rt_sigqueueinfo
+  { __NR_rt_sigqueueinfo, "rt_sigqueueinfo" },
+#endif
+#ifdef __NR_rt_sigreturn
+  { __NR_rt_sigreturn, "rt_sigreturn" },
+#endif
+#ifdef __NR_rt_sigsuspend
+  { __NR_rt_sigsuspend, "rt_sigsuspend" },
+#endif
+#ifdef __NR_rt_sigtimedwait
+  { __NR_rt_sigtimedwait, "rt_sigtimedwait" },
+#endif
+#ifdef __NR_rt_tgsigqueueinfo
+  { __NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" },
+#endif
+#ifdef __NR_sched_get_priority_max
+  { __NR_sched_get_priority_max, "sched_get_priority_max" },
+#endif
+#ifdef __NR_sched_get_priority_min
+  { __NR_sched_get_priority_min, "sched_get_priority_min" },
+#endif
+#ifdef __NR_sched_getaffinity
+  { __NR_sched_getaffinity, "sched_getaffinity" },
+#endif
+#ifdef __NR_sched_getparam
+  { __NR_sched_getparam, "sched_getparam" },
+#endif
+#ifdef __NR_sched_getscheduler
+  { __NR_sched_getscheduler, "sched_getscheduler" },
+#endif
+#ifdef __NR_sched_rr_get_interval
+  { __NR_sched_rr_get_interval, "sched_rr_get_interval" },
+#endif
+#ifdef __NR_sched_setaffinity
+  { __NR_sched_setaffinity, "sched_setaffinity" },
+#endif
+#ifdef __NR_sched_setparam
+  { __NR_sched_setparam, "sched_setparam" },
+#endif
+#ifdef __NR_sched_setscheduler
+  { __NR_sched_setscheduler, "sched_setscheduler" },
+#endif
+#ifdef __NR_sched_yield
+  { __NR_sched_yield, "sched_yield" },
+#endif
+#ifdef __NR_security
+  { __NR_security, "security" },
+#endif
+#ifdef __NR_select
+  { __NR_select, "select" },
+#endif
+#ifdef __NR_semctl
+  { __NR_semctl, "semctl" },
+#endif
+#ifdef __NR_semget
+  { __NR_semget, "semget" },
+#endif
+#ifdef __NR_semop
+  { __NR_semop, "semop" },
+#endif
+#ifdef __NR_semtimedop
+  { __NR_semtimedop, "semtimedop" },
+#endif
+#ifdef __NR_sendfile
+  { __NR_sendfile, "sendfile" },
+#endif
+#ifdef __NR_sendfile64
+  { __NR_sendfile64, "sendfile64" },
+#endif
+#ifdef __NR_sendmmsg
+  { __NR_sendmmsg, "sendmmsg" },
+#endif
+#ifdef __NR_sendmsg
+  { __NR_sendmsg, "sendmsg" },
+#endif
+#ifdef __NR_sendto
+  { __NR_sendto, "sendto" },
+#endif
+#ifdef __NR_set_mempolicy
+  { __NR_set_mempolicy, "set_mempolicy" },
+#endif
+#ifdef __NR_set_robust_list
+  { __NR_set_robust_list, "set_robust_list" },
+#endif
+#ifdef __NR_set_thread_area
+  { __NR_set_thread_area, "set_thread_area" },
+#endif
+#ifdef __NR_set_tid_address
+  { __NR_set_tid_address, "set_tid_address" },
+#endif
+#ifdef __NR_setdomainname
+  { __NR_setdomainname, "setdomainname" },
+#endif
+#ifdef __NR_setfsgid
+  { __NR_setfsgid, "setfsgid" },
+#endif
+#ifdef __NR_setfsgid32
+  { __NR_setfsgid32, "setfsgid32" },
+#endif
+#ifdef __NR_setfsuid
+  { __NR_setfsuid, "setfsuid" },
+#endif
+#ifdef __NR_setfsuid32
+  { __NR_setfsuid32, "setfsuid32" },
+#endif
+#ifdef __NR_setgid
+  { __NR_setgid, "setgid" },
+#endif
+#ifdef __NR_setgid32
+  { __NR_setgid32, "setgid32" },
+#endif
+#ifdef __NR_setgroups
+  { __NR_setgroups, "setgroups" },
+#endif
+#ifdef __NR_setgroups32
+  { __NR_setgroups32, "setgroups32" },
+#endif
+#ifdef __NR_sethostname
+  { __NR_sethostname, "sethostname" },
+#endif
+#ifdef __NR_setitimer
+  { __NR_setitimer, "setitimer" },
+#endif
+#ifdef __NR_setns
+  { __NR_setns, "setns" },
+#endif
+#ifdef __NR_setpgid
+  { __NR_setpgid, "setpgid" },
+#endif
+#ifdef __NR_setpriority
+  { __NR_setpriority, "setpriority" },
+#endif
+#ifdef __NR_setregid
+  { __NR_setregid, "setregid" },
+#endif
+#ifdef __NR_setregid32
+  { __NR_setregid32, "setregid32" },
+#endif
+#ifdef __NR_setresgid
+  { __NR_setresgid, "setresgid" },
+#endif
+#ifdef __NR_setresgid32
+  { __NR_setresgid32, "setresgid32" },
+#endif
+#ifdef __NR_setresuid
+  { __NR_setresuid, "setresuid" },
+#endif
+#ifdef __NR_setresuid32
+  { __NR_setresuid32, "setresuid32" },
+#endif
+#ifdef __NR_setreuid
+  { __NR_setreuid, "setreuid" },
+#endif
+#ifdef __NR_setreuid32
+  { __NR_setreuid32, "setreuid32" },
+#endif
+#ifdef __NR_setrlimit
+  { __NR_setrlimit, "setrlimit" },
+#endif
+#ifdef __NR_setsid
+  { __NR_setsid, "setsid" },
+#endif
+#ifdef __NR_setsockopt
+  { __NR_setsockopt, "setsockopt" },
+#endif
+#ifdef __NR_settimeofday
+  { __NR_settimeofday, "settimeofday" },
+#endif
+#ifdef __NR_setuid
+  { __NR_setuid, "setuid" },
+#endif
+#ifdef __NR_setuid32
+  { __NR_setuid32, "setuid32" },
+#endif
+#ifdef __NR_setxattr
+  { __NR_setxattr, "setxattr" },
+#endif
+#ifdef __NR_sgetmask
+  { __NR_sgetmask, "sgetmask" },
+#endif
+#ifdef __NR_shmat
+  { __NR_shmat, "shmat" },
+#endif
+#ifdef __NR_shmctl
+  { __NR_shmctl, "shmctl" },
+#endif
+#ifdef __NR_shmdt
+  { __NR_shmdt, "shmdt" },
+#endif
+#ifdef __NR_shmget
+  { __NR_shmget, "shmget" },
+#endif
+#ifdef __NR_shutdown
+  { __NR_shutdown, "shutdown" },
+#endif
+#ifdef __NR_sigaction
+  { __NR_sigaction, "sigaction" },
+#endif
+#ifdef __NR_sigaltstack
+  { __NR_sigaltstack, "sigaltstack" },
+#endif
+#ifdef __NR_signal
+  { __NR_signal, "signal" },
+#endif
+#ifdef __NR_signalfd
+  { __NR_signalfd, "signalfd" },
+#endif
+#ifdef __NR_signalfd4
+  { __NR_signalfd4, "signalfd4" },
+#endif
+#ifdef __NR_sigpending
+  { __NR_sigpending, "sigpending" },
+#endif
+#ifdef __NR_sigprocmask
+  { __NR_sigprocmask, "sigprocmask" },
+#endif
+#ifdef __NR_sigreturn
+  { __NR_sigreturn, "sigreturn" },
+#endif
+#ifdef __NR_sigsuspend
+  { __NR_sigsuspend, "sigsuspend" },
+#endif
+#ifdef __NR_socket
+  { __NR_socket, "socket" },
+#endif
+#ifdef __NR_socketcall
+  { __NR_socketcall, "socketcall" },
+#endif
+#ifdef __NR_socketpair
+  { __NR_socketpair, "socketpair" },
+#endif
+#ifdef __NR_splice
+  { __NR_splice, "splice" },
+#endif
+#ifdef __NR_ssetmask
+  { __NR_ssetmask, "ssetmask" },
+#endif
+#ifdef __NR_stat
+  { __NR_stat, "stat" },
+#endif
+#ifdef __NR_stat64
+  { __NR_stat64, "stat64" },
+#endif
+#ifdef __NR_statfs
+  { __NR_statfs, "statfs" },
+#endif
+#ifdef __NR_statfs64
+  { __NR_statfs64, "statfs64" },
+#endif
+#ifdef __NR_stime
+  { __NR_stime, "stime" },
+#endif
+#ifdef __NR_stty
+  { __NR_stty, "stty" },
+#endif
+#ifdef __NR_swapoff
+  { __NR_swapoff, "swapoff" },
+#endif
+#ifdef __NR_swapon
+  { __NR_swapon, "swapon" },
+#endif
+#ifdef __NR_symlink
+  { __NR_symlink, "symlink" },
+#endif
+#ifdef __NR_symlinkat
+  { __NR_symlinkat, "symlinkat" },
+#endif
+#ifdef __NR_sync
+  { __NR_sync, "sync" },
+#endif
+#ifdef __NR_sync_file_range
+  { __NR_sync_file_range, "sync_file_range" },
+#endif
+#ifdef __NR_syncfs
+  { __NR_syncfs, "syncfs" },
+#endif
+#ifdef __NR_sysfs
+  { __NR_sysfs, "sysfs" },
+#endif
+#ifdef __NR_sysinfo
+  { __NR_sysinfo, "sysinfo" },
+#endif
+#ifdef __NR_syslog
+  { __NR_syslog, "syslog" },
+#endif
+#ifdef __NR_tee
+  { __NR_tee, "tee" },
+#endif
+#ifdef __NR_tgkill
+  { __NR_tgkill, "tgkill" },
+#endif
+#ifdef __NR_time
+  { __NR_time, "time" },
+#endif
+#ifdef __NR_timer_create
+  { __NR_timer_create, "timer_create" },
+#endif
+#ifdef __NR_timer_delete
+  { __NR_timer_delete, "timer_delete" },
+#endif
+#ifdef __NR_timer_getoverrun
+  { __NR_timer_getoverrun, "timer_getoverrun" },
+#endif
+#ifdef __NR_timer_gettime
+  { __NR_timer_gettime, "timer_gettime" },
+#endif
+#ifdef __NR_timer_settime
+  { __NR_timer_settime, "timer_settime" },
+#endif
+#ifdef __NR_timerfd_create
+  { __NR_timerfd_create, "timerfd_create" },
+#endif
+#ifdef __NR_timerfd_gettime
+  { __NR_timerfd_gettime, "timerfd_gettime" },
+#endif
+#ifdef __NR_timerfd_settime
+  { __NR_timerfd_settime, "timerfd_settime" },
+#endif
+#ifdef __NR_times
+  { __NR_times, "times" },
+#endif
+#ifdef __NR_tkill
+  { __NR_tkill, "tkill" },
+#endif
+#ifdef __NR_truncate
+  { __NR_truncate, "truncate" },
+#endif
+#ifdef __NR_truncate64
+  { __NR_truncate64, "truncate64" },
+#endif
+#ifdef __NR_tuxcall
+  { __NR_tuxcall, "tuxcall" },
+#endif
+#ifdef __NR_ugetrlimit
+  { __NR_ugetrlimit, "ugetrlimit" },
+#endif
+#ifdef __NR_ulimit
+  { __NR_ulimit, "ulimit" },
+#endif
+#ifdef __NR_umask
+  { __NR_umask, "umask" },
+#endif
+#ifdef __NR_umount
+  { __NR_umount, "umount" },
+#endif
+#ifdef __NR_umount2
+  { __NR_umount2, "umount2" },
+#endif
+#ifdef __NR_uname
+  { __NR_uname, "uname" },
+#endif
+#ifdef __NR_unlink
+  { __NR_unlink, "unlink" },
+#endif
+#ifdef __NR_unlinkat
+  { __NR_unlinkat, "unlinkat" },
+#endif
+#ifdef __NR_unshare
+  { __NR_unshare, "unshare" },
+#endif
+#ifdef __NR_uselib
+  { __NR_uselib, "uselib" },
+#endif
+#ifdef __NR_ustat
+  { __NR_ustat, "ustat" },
+#endif
+#ifdef __NR_utime
+  { __NR_utime, "utime" },
+#endif
+#ifdef __NR_utimensat
+  { __NR_utimensat, "utimensat" },
+#endif
+#ifdef __NR_utimes
+  { __NR_utimes, "utimes" },
+#endif
+#ifdef __NR_vfork
+  { __NR_vfork, "vfork" },
+#endif
+#ifdef __NR_vhangup
+  { __NR_vhangup, "vhangup" },
+#endif
+#ifdef __NR_vm86
+  { __NR_vm86, "vm86" },
+#endif
+#ifdef __NR_vm86old
+  { __NR_vm86old, "vm86old" },
+#endif
+#ifdef __NR_vmsplice
+  { __NR_vmsplice, "vmsplice" },
+#endif
+#ifdef __NR_vserver
+  { __NR_vserver, "vserver" },
+#endif
+#ifdef __NR_wait4
+  { __NR_wait4, "wait4" },
+#endif
+#ifdef __NR_waitid
+  { __NR_waitid, "waitid" },
+#endif
+#ifdef __NR_waitpid
+  { __NR_waitpid, "waitpid" },
+#endif
+#ifdef __NR_write
+  { __NR_write, "write" },
+#endif
+#ifdef __NR_writev
+  { __NR_writev, "writev" },
+#endif
+  {0, NULL}
+};
+

+ 297 - 137
src/common/sandbox.c

@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #include "sandbox.h"
+#include "container.h"
 #include "torlog.h"
 #include "torint.h"
 #include "util.h"
@@ -76,6 +77,13 @@ static sb_addr_info_t *sb_addr_info = NULL;
 
 #undef SCMP_CMP
 #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
+#define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
+/* We use a wrapper here because these masked comparisons seem to be pretty
+ * verbose. Also, it's important to cast to scmp_datum_t before negating the
+ * mask, since otherwise the negation might get applied to a 32 bit value, and
+ * the high bits of the value might get masked out improperly. */
+#define SCMP_CMP_MASKED(a,b,c) \
+  SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
 
 /** Variable used for storing all syscall numbers that will be allowed with the
  * stage 1 general Tor sandbox.
@@ -121,7 +129,6 @@ static int filter_nopar_gen[] = {
     SCMP_SYS(mmap),
     SCMP_SYS(munmap),
     SCMP_SYS(read),
-    SCMP_SYS(rename),
     SCMP_SYS(rt_sigreturn),
     SCMP_SYS(set_robust_list),
 #ifdef __NR_sigreturn
@@ -159,6 +166,19 @@ static int filter_nopar_gen[] = {
     SCMP_SYS(unlink)
 };
 
+/* These macros help avoid the error where the number of filters we add on a
+ * single rule don't match the arg_cnt param. */
+#define seccomp_rule_add_0(ctx,act,call) \
+  seccomp_rule_add((ctx),(act),(call),0)
+#define seccomp_rule_add_1(ctx,act,call,f1) \
+  seccomp_rule_add((ctx),(act),(call),1,(f1))
+#define seccomp_rule_add_2(ctx,act,call,f1,f2)  \
+  seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
+#define seccomp_rule_add_3(ctx,act,call,f1,f2,f3)       \
+  seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
+#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4)      \
+  seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
+
 /**
  * Function responsible for setting up the rt_sigaction syscall for
  * the seccomp filter sandbox.
@@ -176,7 +196,7 @@ sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void) filter;
 
   for (i = 0; i < ARRAY_LENGTH(param); i++) {
-    rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 1,
+    rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
         SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
     if (rc)
       break;
@@ -197,11 +217,11 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
   // for each dynamic parameter filters
   for (elem = filter; elem != NULL; elem = elem->next) {
-    smp_param_t *param = (smp_param_t*) elem->param;
+    smp_param_t *param = elem->param;
 
     if (param != NULL && param->prot == 1 && param->syscall
         == SCMP_SYS(execve)) {
-      rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1,
+      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve),
           SCMP_CMP(0, SCMP_CMP_EQ, param->value));
       if (rc != 0) {
         log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received "
@@ -222,7 +242,7 @@ static int
 sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 {
   (void) filter;
-  return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1,
+  return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
        SCMP_CMP(0, SCMP_CMP_EQ, 0));
 }
 
@@ -237,15 +257,15 @@ sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void)filter;
 
 #ifdef __i386__
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
       SCMP_CMP(0, SCMP_CMP_EQ, 18));
   if (rc) {
     return rc;
   }
 #endif
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 1,
-      SCMP_CMP(3, SCMP_CMP_EQ, SOCK_CLOEXEC));
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
+                   SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
   if (rc) {
     return rc;
   }
@@ -264,49 +284,49 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void)filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
        SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
        SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
        SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
        SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
        SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
        SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
        SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
        SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
   if (rc) {
     return rc;
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
   if (rc) {
@@ -333,7 +353,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
     if (param != NULL && param->prot == 1 && param->syscall
         == SCMP_SYS(open)) {
-      rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1,
+      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
             SCMP_CMP(0, SCMP_CMP_EQ, param->value));
       if (rc != 0) {
         log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
@@ -343,8 +363,8 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
     }
   }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(-1), SCMP_SYS(open), 1,
-        SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC));
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open),
+                SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY, O_RDONLY));
   if (rc != 0) {
     log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp "
         "error %d", rc);
@@ -354,6 +374,54 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   return 0;
 }
 
+static int
+sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+  int rc;
+  (void) filter;
+  (void) ctx;
+
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl));
+  if (rc != 0) {
+    log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, "
+        "received libseccomp error %d", rc);
+    return rc;
+  }
+
+  return 0;
+}
+
+/**
+ * Function responsible for setting up the rename syscall for
+ * the seccomp filter sandbox.
+ */
+static int
+sb_rename(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(rename)) {
+
+      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
+            SCMP_CMP(0, SCMP_CMP_EQ, param->value),
+            SCMP_CMP(1, SCMP_CMP_EQ, param->value2));
+      if (rc != 0) {
+        log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
+            "libseccomp error %d", rc);
+        return rc;
+      }
+    }
+  }
+
+  return 0;
+}
+
 /**
  * Function responsible for setting up the openat syscall for
  * the seccomp filter sandbox.
@@ -370,7 +438,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
     if (param != NULL && param->prot == 1 && param->syscall
         == SCMP_SYS(openat)) {
-      rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1,
+      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
           SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD),
           SCMP_CMP(1, SCMP_CMP_EQ, param->value),
           SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
@@ -394,43 +462,40 @@ static int
 sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 {
   int rc = 0;
+  int i;
   (void) filter;
 
 #ifdef __i386__
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
   if (rc)
     return rc;
 #endif
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
       SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
-      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK),
-      SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
+      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3,
-      SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
-      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC),
-      SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP));
-  if (rc)
-    return rc;
+  for (i = 0; i < 2; ++i) {
+    const int pf = i ? PF_INET : PF_INET6;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3,
-      SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
-      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK),
+    rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
+      SCMP_CMP(0, SCMP_CMP_EQ, pf),
+      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
       SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP));
-  if (rc)
-    return rc;
+    if (rc)
+      return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3,
-      SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
-      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK),
+    rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
+      SCMP_CMP(0, SCMP_CMP_EQ, pf),
+      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
       SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
-  if (rc)
-    return rc;
+    if (rc)
+      return rc;
+  }
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3,
+  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
       SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
       SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW),
       SCMP_CMP(2, SCMP_CMP_EQ, 0));
@@ -451,12 +516,12 @@ sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void) filter;
 
 #ifdef __i386__
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0);
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
   if (rc)
     return rc;
 #endif
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
       SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
       SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
   if (rc)
@@ -476,19 +541,19 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void) filter;
 
 #ifdef __i386__
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0);
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
   if (rc)
     return rc;
 #endif
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
       SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
       SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
   if (rc)
     return rc;
 
 #ifdef IP_TRANSPARENT
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
       SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
       SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
   if (rc)
@@ -509,12 +574,12 @@ sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void) filter;
 
 #ifdef __i386__
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0);
+  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
   if (rc)
     return rc;
 #endif
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
       SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
       SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
   if (rc)
@@ -534,23 +599,23 @@ sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
       SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
       SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
       SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
       SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
       SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
       SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
   if (rc)
@@ -572,17 +637,17 @@ sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
       SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
       SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
       SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
   if (rc)
     return rc;
@@ -603,7 +668,7 @@ sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
       SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
   if (rc)
     return rc;
@@ -624,12 +689,12 @@ sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
   if (rc)
     return rc;
@@ -647,12 +712,12 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
       SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
       SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
   if (rc)
     return rc;
@@ -672,12 +737,12 @@ sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
       SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
       SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
   if (rc)
     return rc;
@@ -696,18 +761,18 @@ sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   (void) filter;
 
   // can remove
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
       SCMP_CMP(1, SCMP_CMP_EQ,
           FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
       SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
   if (rc)
     return rc;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
       SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
   if (rc)
     return rc;
@@ -727,7 +792,7 @@ sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 1,
+  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
       SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
   if (rc)
     return rc;
@@ -745,7 +810,7 @@ sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
   int rc = 0;
   (void) filter;
 
-  rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 2,
+  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll),
       SCMP_CMP(1, SCMP_CMP_EQ, 1),
       SCMP_CMP(2, SCMP_CMP_EQ, 10));
   if (rc)
@@ -771,7 +836,7 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
 
     if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
         || param->syscall == SCMP_SYS(stat64))) {
-      rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 1,
+      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
           SCMP_CMP(0, SCMP_CMP_EQ, param->value));
       if (rc != 0) {
         log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
@@ -800,6 +865,8 @@ static sandbox_filter_func_t filter_func[] = {
 #endif
     sb_open,
     sb_openat,
+    sb__sysctl,
+    sb_rename,
 #ifdef __NR_fcntl64
     sb_fcntl64,
 #endif
@@ -820,7 +887,7 @@ static sandbox_filter_func_t filter_func[] = {
     sb_socketpair
 };
 
-const char*
+const char *
 sandbox_intern_string(const char *str)
 {
   sandbox_cfg_t *elem;
@@ -831,15 +898,65 @@ sandbox_intern_string(const char *str)
   for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
     smp_param_t *param = elem->param;
 
-    if (param->prot && !strcmp(str, (char*)(param->value))) {
-      return (char*)(param->value);
+    if (param->prot) {
+      if (!strcmp(str, (char*)(param->value))) {
+        return (char*)param->value;
+      }
+      if (param->value2 && !strcmp(str, (char*)param->value2)) {
+        return (char*)param->value2;
+      }
     }
   }
 
-  log_info(LD_GENERAL, "(Sandbox) Parameter %s not found", str);
+  if (sandbox_active)
+    log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
   return str;
 }
 
+/** DOCDOC */
+static int
+prot_strings_helper(strmap_t *locations,
+                    char **pr_mem_next_p,
+                    size_t *pr_mem_left_p,
+                    intptr_t *value_p)
+{
+  char *param_val;
+  size_t param_size;
+  void *location;
+
+  if (*value_p == 0)
+    return 0;
+
+  param_val = (char*) *value_p;
+  param_size = strlen(param_val) + 1;
+  location = strmap_get(locations, param_val);
+
+  if (location) {
+    // We already interned this string.
+    tor_free(param_val);
+    *value_p = (intptr_t) location;
+    return 0;
+  } else if (*pr_mem_left_p >= param_size) {
+    // copy to protected
+    location = *pr_mem_next_p;
+    memcpy(location, param_val, param_size);
+
+    // re-point el parameter to protected
+    tor_free(param_val);
+    *value_p = (intptr_t) location;
+
+    strmap_set(locations, location, location); /* good real estate advice */
+
+    // move next available protected memory
+    *pr_mem_next_p += param_size;
+    *pr_mem_left_p -= param_size;
+    return 0;
+  } else {
+    log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
+    return -1;
+  }
+}
+
 /**
  * Protects all the strings in the sandbox's parameter list configuration. It
  * works by calculating the total amount of memory required by the parameter
@@ -853,10 +970,13 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
   size_t pr_mem_size = 0, pr_mem_left = 0;
   char *pr_mem_next = NULL, *pr_mem_base;
   sandbox_cfg_t *el = NULL;
+  strmap_t *locations = NULL;
 
-  // get total number of bytes required to mmap
+  // get total number of bytes required to mmap. (Overestimate.)
   for (el = cfg; el != NULL; el = el->next) {
-    pr_mem_size += strlen((char*) ((smp_param_t*)el->param)->value) + 1;
+    pr_mem_size += strlen((char*) el->param->value) + 1;
+    if (el->param->value2)
+      pr_mem_size += strlen((char*) el->param->value2) + 1;
   }
 
   // allocate protected memory with MALLOC_MP_LIM canary
@@ -872,31 +992,21 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
   pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
   pr_mem_left = pr_mem_size;
 
+  locations = strmap_new();
+
   // change el value pointer to protected
   for (el = cfg; el != NULL; el = el->next) {
-    char *param_val = (char*)((smp_param_t *)el->param)->value;
-    size_t param_size = strlen(param_val) + 1;
-
-    if (pr_mem_left >= param_size) {
-      // copy to protected
-      memcpy(pr_mem_next, param_val, param_size);
-
-      // re-point el parameter to protected
-      {
-        void *old_val = (void *) ((smp_param_t*)el->param)->value;
-        tor_free(old_val);
-      }
-      ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next;
-      ((smp_param_t*)el->param)->prot = 1;
-
-      // move next available protected memory
-      pr_mem_next += param_size;
-      pr_mem_left -= param_size;
-    } else {
-      log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
+    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
+                            &el->param->value) < 0) {
+      ret = -2;
+      goto out;
+    }
+    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
+                            &el->param->value2) < 0) {
       ret = -2;
       goto out;
     }
+    el->param->prot = 1;
   }
 
   // protecting from writes
@@ -911,7 +1021,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
    * Setting sandbox restrictions so the string memory cannot be tampered with
    */
   // no mremap of the protected base address
-  ret = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap), 1,
+  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
       SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
   if (ret) {
     log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
@@ -919,7 +1029,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
   }
 
   // no munmap of the protected base address
-  ret = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap), 1,
+  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
         SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
   if (ret) {
     log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
@@ -936,7 +1046,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
    * There is a restriction on how much you can mprotect with R|W up to the
    * size of the canary.
    */
-  ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2,
+  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
       SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
       SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
@@ -945,7 +1055,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
     return ret;
   }
 
-  ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2,
+  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
       SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
           MALLOC_MP_LIM),
       SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
@@ -956,7 +1066,8 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
   }
 
  out:
-   return ret;
+  strmap_free(locations, NULL);
+  return ret;
 }
 
 /**
@@ -966,22 +1077,27 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
  * point.
  */
 static sandbox_cfg_t*
-new_element(int syscall, int index, intptr_t value)
+new_element2(int syscall, intptr_t value, intptr_t value2)
 {
   smp_param_t *param = NULL;
 
-  sandbox_cfg_t *elem = tor_malloc(sizeof(sandbox_cfg_t));
-  elem->param = tor_malloc(sizeof(smp_param_t));
+  sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
+  param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
 
-  param = elem->param;
   param->syscall = syscall;
-  param->pindex = index;
   param->value = value;
+  param->value2 = value2;
   param->prot = 0;
 
   return elem;
 }
 
+static sandbox_cfg_t*
+new_element(int syscall, intptr_t value)
+{
+  return new_element2(syscall, value, 0);
+}
+
 #ifdef __NR_stat64
 #define SCMP_stat SCMP_SYS(stat64)
 #else
@@ -989,11 +1105,11 @@ new_element(int syscall, int index, intptr_t value)
 #endif
 
 int
-sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, int fr)
+sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
 {
   sandbox_cfg_t *elem = NULL;
 
-  elem = new_element(SCMP_stat, 0, (intptr_t)(void*) tor_strdup(file));
+  elem = new_element(SCMP_stat, (intptr_t)(void*) file);
   if (!elem) {
     log_err(LD_BUG,"(Sandbox) failed to register parameter!");
     return -1;
@@ -1002,7 +1118,6 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, int fr)
   elem->next = *cfg;
   *cfg = elem;
 
-  if (fr) tor_free(file);
   return 0;
 }
 
@@ -1016,9 +1131,7 @@ sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...)
   va_start(ap, cfg);
 
   while ((fn = va_arg(ap, char*)) != NULL) {
-    int fr = va_arg(ap, int);
-
-    rc = sandbox_cfg_allow_stat_filename(cfg, fn, fr);
+    rc = sandbox_cfg_allow_stat_filename(cfg, fn);
     if (rc) {
       log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail");
       goto end;
@@ -1031,11 +1144,11 @@ sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...)
 }
 
 int
-sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr)
+sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
 {
   sandbox_cfg_t *elem = NULL;
 
-  elem = new_element(SCMP_SYS(open), 0, (intptr_t)(void *)tor_strdup(file));
+  elem = new_element(SCMP_SYS(open), (intptr_t)(void *) file);
   if (!elem) {
     log_err(LD_BUG,"(Sandbox) failed to register parameter!");
     return -1;
@@ -1044,7 +1157,25 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr)
   elem->next = *cfg;
   *cfg = elem;
 
-  if (fr) tor_free(file);
+  return 0;
+}
+
+int
+sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
+{
+  sandbox_cfg_t *elem = NULL;
+
+  elem = new_element2(SCMP_SYS(rename),
+                      (intptr_t)(void *) file1,
+                      (intptr_t)(void *) file2);
+
+  if (!elem) {
+    log_err(LD_BUG,"(Sandbox) failed to register parameter!");
+    return -1;
+  }
+
+  elem->next = *cfg;
+  *cfg = elem;
 
   return 0;
 }
@@ -1059,9 +1190,7 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...)
   va_start(ap, cfg);
 
   while ((fn = va_arg(ap, char*)) != NULL) {
-    int fr = va_arg(ap, int);
-
-    rc = sandbox_cfg_allow_open_filename(cfg, fn, fr);
+    rc = sandbox_cfg_allow_open_filename(cfg, fn);
     if (rc) {
       log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_open_filename_array fail");
       goto end;
@@ -1074,11 +1203,11 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...)
 }
 
 int
-sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr)
+sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
 {
   sandbox_cfg_t *elem = NULL;
 
-  elem = new_element(SCMP_SYS(openat), 1, (intptr_t)(void *)tor_strdup(file));
+  elem = new_element(SCMP_SYS(openat), (intptr_t)(void *) file);
   if (!elem) {
     log_err(LD_BUG,"(Sandbox) failed to register parameter!");
     return -1;
@@ -1087,8 +1216,6 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr)
   elem->next = *cfg;
   *cfg = elem;
 
-  if (fr) tor_free(file);
-
   return 0;
 }
 
@@ -1102,9 +1229,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...)
   va_start(ap, cfg);
 
   while ((fn = va_arg(ap, char*)) != NULL) {
-    int fr = va_arg(ap, int);
-
-    rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr);
+    rc = sandbox_cfg_allow_openat_filename(cfg, fn);
     if (rc) {
       log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail");
       goto end;
@@ -1121,7 +1246,7 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com)
 {
   sandbox_cfg_t *elem = NULL;
 
-  elem = new_element(SCMP_SYS(execve), 1, (intptr_t)(void *)tor_strdup(com));
+  elem = new_element(SCMP_SYS(execve), (intptr_t)(void *) com);
   if (!elem) {
     log_err(LD_BUG,"(Sandbox) failed to register parameter!");
     return -1;
@@ -1259,7 +1384,7 @@ add_noparam_filter(scmp_filter_ctx ctx)
 
   // add general filters
   for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
-    rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i], 0);
+    rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
     if (rc != 0) {
       log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), "
           "received libseccomp error %d", i, filter_nopar_gen[i], rc);
@@ -1319,6 +1444,24 @@ install_syscall_filter(sandbox_cfg_t* cfg)
   return (rc < 0 ? -rc : rc);
 }
 
+#include "linux_syscalls.inc"
+static const char *
+get_syscall_name(int syscall_num)
+{
+  int i;
+  for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
+    if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
+      return SYSCALLS_BY_NUMBER[i].syscall_name;
+  }
+
+  {
+     static char syscall_name_buf[64];
+     format_dec_number_sigsafe(syscall_num,
+                               syscall_name_buf, sizeof(syscall_name_buf));
+     return syscall_name_buf;
+  }
+}
+
 #ifdef USE_BACKTRACE
 #define MAX_DEPTH 256
 static void *syscall_cb_buf[MAX_DEPTH];
@@ -1333,7 +1476,7 @@ static void
 sigsys_debugging(int nr, siginfo_t *info, void *void_context)
 {
   ucontext_t *ctx = (ucontext_t *) (void_context);
-  char number[32];
+  const char *syscall_name;
   int syscall;
 #ifdef USE_BACKTRACE
   int depth;
@@ -1358,9 +1501,10 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context)
   clean_backtrace(syscall_cb_buf, depth, ctx);
 #endif
 
-  format_dec_number_sigsafe(syscall, number, sizeof(number));
+  syscall_name = get_syscall_name(syscall);
+
   tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
-                      number,
+                      syscall_name,
                       ")\n",
                       NULL);
 
@@ -1421,7 +1565,8 @@ register_cfg(sandbox_cfg_t* cfg)
     return 0;
   }
 
-  for (elem = filter_dynamic; elem->next != NULL; elem = elem->next);
+  for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
+    ;
 
   elem->next = cfg;
 
@@ -1450,6 +1595,11 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
   return 0;
 }
 
+int
+sandbox_is_active(void)
+{
+  return sandbox_active != 0;
+}
 #endif // USE_LIBSECCOMP
 
 sandbox_cfg_t*
@@ -1485,10 +1635,9 @@ sandbox_init(sandbox_cfg_t *cfg)
 
 #ifndef USE_LIBSECCOMP
 int
-sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file,
-                                int fr)
+sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
 {
-  (void)cfg; (void)file; (void)fr;
+  (void)cfg; (void)file;
   return 0;
 }
 
@@ -1500,10 +1649,9 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...)
 }
 
 int
-sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file,
-                                  int fr)
+sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
 {
-  (void)cfg; (void)file; (void)fr;
+  (void)cfg; (void)file;
   return 0;
 }
 
@@ -1529,10 +1677,9 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...)
 }
 
 int
-sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file,
-                                int fr)
+sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
 {
-  (void)cfg; (void)file; (void)fr;
+  (void)cfg; (void)file;
   return 0;
 }
 
@@ -1542,5 +1689,18 @@ sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...)
   (void)cfg;
   return 0;
 }
+
+int
+sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
+{
+  (void)cfg; (void)file1; (void)file2;
+  return 0;
+}
+
+int
+sandbox_is_active(void)
+{
+  return 0;
+}
 #endif
 

+ 27 - 38
src/common/sandbox.h

@@ -65,10 +65,10 @@ typedef struct smp_param {
   /** syscall associated with parameter. */
   int syscall;
 
-  /** parameter index. */
-  int pindex;
   /** parameter value. */
   intptr_t value;
+  /** parameter value, second argument. */
+  intptr_t value2;
 
   /**  parameter flag (0 = not protected, 1 = protected). */
   int prot;
@@ -85,7 +85,7 @@ struct sandbox_cfg_elem {
   SB_IMPL implem;
 
   /** Configuration parameter. */
-  void *param;
+  smp_param_t *param;
 
   /** Next element of the configuration*/
   struct sandbox_cfg_elem *next;
@@ -167,81 +167,70 @@ sandbox_cfg_t * sandbox_cfg_new(void);
 
 /**
  * Function used to add a open allowed filename to a supplied configuration.
- * The (char*) specifies the path to the allowed file, fr = 1 tells the
- * function that the char* needs to be free-ed, 0 means the pointer does not
- * need to be free-ed.
+ * The (char*) specifies the path to the allowed file; we take ownership
+ * of the pointer.
  */
-int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file,
-    int fr);
+int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file);
+
+/**DOCDOC*/
+int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2);
 
 /** Function used to add a series of open allowed filenames to a supplied
  * configuration.
  *  @param cfg  sandbox configuration.
- *  @param ... all future parameters are specified as pairs of <(char*), 1 / 0>
- *    the char* specifies the path to the allowed file, 1 tells the function
- *    that the char* needs to be free-ed, 0 means the pointer does not need to
- *    be free-ed; the final parameter needs to be <NULL, 0>.
- */
+ *  @param ... a list of stealable pointers to permitted files.  The last
+ *  one must be NULL.
+*/
 int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...);
 
 /**
  * Function used to add a openat allowed filename to a supplied configuration.
- * The (char*) specifies the path to the allowed file, fr = 1 tells the
- * function that the char* needs to be free-ed, 0 means the pointer does not
- * need to be free-ed.
+ * The (char*) specifies the path to the allowed file; we steal the pointer to
+ * that file.
  */
-int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file,
-    int fr);
+int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file);
 
 /** Function used to add a series of openat allowed filenames to a supplied
  * configuration.
  *  @param cfg  sandbox configuration.
- *  @param ... all future parameters are specified as pairs of <(char*), 1 / 0>
- *    the char* specifies the path to the allowed file, 1 tells the function
- *    that the char* needs to be free-ed, 0 means the pointer does not need to
- *    be free-ed; the final parameter needs to be <NULL, 0>.
+ *  @param ... a list of stealable pointers to permitted files.  The last
+ *  one must be NULL.
  */
 int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...);
 
 /**
  * Function used to add a execve allowed filename to a supplied configuration.
- * The (char*) specifies the path to the allowed file, fr = 1 tells the
- * function that the char* needs to be free-ed, 0 means the pointer does not
- * need to be free-ed.
+ * The (char*) specifies the path to the allowed file; that pointer is stolen.
  */
 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com);
 
 /** Function used to add a series of execve allowed filenames to a supplied
  * configuration.
  *  @param cfg  sandbox configuration.
- *  @param ... all future parameters are specified as pairs of <(char*), 1 / 0>
- *    the char* specifies the path to the allowed file, 1 tells the function
- *    that the char* needs to be free-ed, 0 means the pointer does not need to
- *    be free-ed; the final parameter needs to be <NULL, 0>.
+ *  @param ... an array of stealable pointers to permitted files.  The last
+ *  one must be NULL.
  */
 int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...);
 
 /**
  * Function used to add a stat/stat64 allowed filename to a configuration.
- * The (char*) specifies the path to the allowed file, fr = 1 tells the
- * function that the char* needs to be free-ed, 0 means the pointer does not
- * need to be free-ed.
+ * The (char*) specifies the path to the allowed file; that pointer is stolen.
  */
-int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file,
-    int fr);
+int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file);
 
 /** Function used to add a series of stat64 allowed filenames to a supplied
  * configuration.
  *  @param cfg  sandbox configuration.
- *  @param ... all future parameters are specified as pairs of <(char*), 1 / 0>
- *    the char* specifies the path to the allowed file, 1 tells the function
- *    that the char* needs to be free-ed, 0 means the pointer does not need to
- *    be free-ed; the final parameter needs to be <NULL, 0>.
+ *  @param ... an array of stealable pointers to permitted files.  The last
+ *  one must be NULL.
  */
 int sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...);
 
 /** Function used to initialise a sandbox configuration.*/
 int sandbox_init(sandbox_cfg_t* cfg);
 
+/** Return true iff the sandbox is turned on. */
+int sandbox_is_active(void);
+
 #endif /* SANDBOX_H_ */
 

+ 2 - 0
src/common/util.c

@@ -1830,6 +1830,7 @@ file_status(const char *fname)
   int r;
   f = tor_strdup(fname);
   clean_name_for_stat(f);
+  log_debug(LD_FS, "stat()ing %s", f);
   r = stat(sandbox_intern_string(f), &st);
   tor_free(f);
   if (r) {
@@ -1880,6 +1881,7 @@ check_private_dir(const char *dirname, cpd_check_t check,
   tor_assert(dirname);
   f = tor_strdup(dirname);
   clean_name_for_stat(f);
+  log_debug(LD_FS, "stat()ing %s", f);
   r = stat(sandbox_intern_string(f), &st);
   tor_free(f);
   if (r) {

+ 55 - 13
src/or/config.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-2013, The Tor Project, Inc. */
@@ -1043,12 +1043,18 @@ options_act_reversible(const or_options_t *old_options, char **msg)
   if (running_tor) {
     int n_ports=0;
     /* We need to set the connection limit before we can open the listeners. */
-    if (set_max_file_descriptors((unsigned)options->ConnLimit,
-                                 &options->ConnLimit_) < 0) {
-      *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
-      goto rollback;
+    if (! sandbox_is_active()) {
+      if (set_max_file_descriptors((unsigned)options->ConnLimit,
+                                   &options->ConnLimit_) < 0) {
+        *msg = tor_strdup("Problem with ConnLimit value. "
+                          "See logs for details.");
+        goto rollback;
+      }
+      set_conn_limit = 1;
+    } else {
+      tor_assert(old_options);
+      options->ConnLimit_ = old_options->ConnLimit_;
     }
-    set_conn_limit = 1;
 
     /* Set up libevent.  (We need to do this before we can register the
      * listeners as listeners.) */
@@ -1132,11 +1138,13 @@ options_act_reversible(const or_options_t *old_options, char **msg)
   if (!running_tor)
     goto commit;
 
-  mark_logs_temp(); /* Close current logs once new logs are open. */
-  logs_marked = 1;
-  if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */
-    *msg = tor_strdup("Failed to init Log options. See logs for details.");
-    goto rollback;
+  if (!sandbox_is_active()) {
+    mark_logs_temp(); /* Close current logs once new logs are open. */
+    logs_marked = 1;
+    if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */
+      *msg = tor_strdup("Failed to init Log options. See logs for details.");
+      goto rollback;
+    }
   }
 
  commit:
@@ -1486,8 +1494,9 @@ options_act(const or_options_t *old_options)
 
   /* Write our PID to the PID file. If we do not have write permissions we
    * will log a warning */
-  if (options->PidFile)
+  if (options->PidFile && !sandbox_is_active()) {
     write_pidfile(options->PidFile);
+  }
 
   /* Register addressmap directives */
   config_register_addressmaps(options);
@@ -3591,6 +3600,12 @@ options_transition_allowed(const or_options_t *old,
     return -1;
   }
 
+  if (old->Sandbox != new_val->Sandbox) {
+    *msg = tor_strdup("While Tor is running, changing Sandbox "
+                      "is not allowed.");
+    return -1;
+  }
+
   if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
     tor_asprintf(msg,
                "While Tor is running, changing DataDirectory "
@@ -3643,6 +3658,32 @@ options_transition_allowed(const or_options_t *old,
     return -1;
   }
 
+  if (sandbox_is_active()) {
+    if (! opt_streq(old->PidFile, new_val->PidFile)) {
+      *msg = tor_strdup("Can't change PidFile while Sandbox is active");
+      return -1;
+    }
+    if (! config_lines_eq(old->Logs, new_val->Logs)) {
+      *msg = tor_strdup("Can't change Logs while Sandbox is active");
+      return -1;
+    }
+    if (old->ConnLimit != new_val->ConnLimit) {
+      *msg = tor_strdup("Can't change ConnLimit while Sandbox is active");
+      return -1;
+    }
+    if (! opt_streq(old->ServerDNSResolvConfFile,
+                    new_val->ServerDNSResolvConfFile)) {
+      *msg = tor_strdup("Can't change ServerDNSResolvConfFile"
+                        " while Sandbox is active");
+      return -1;
+    }
+    if (server_mode(old) != server_mode(new_val)) {
+      *msg = tor_strdup("Can't start/stop being a server while "
+                        "Sandbox is active");
+      return -1;
+    }
+  }
+
   return 0;
 }
 
@@ -6292,7 +6333,7 @@ write_configuration_file(const char *fname, const or_options_t *options)
       ++i;
     }
     log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
-    if (rename(fname, fn_tmp) < 0) {
+    if (tor_rename(fname, fn_tmp) < 0) {//XXXX sandbox doesn't allow
       log_warn(LD_FS,
                "Couldn't rename configuration file \"%s\" to \"%s\": %s",
                fname, fn_tmp, strerror(errno));
@@ -6478,6 +6519,7 @@ remove_file_if_very_old(const char *fname, time_t now)
 #define VERY_OLD_FILE_AGE (28*24*60*60)
   struct stat st;
 
+  log_debug(LD_FS, "stat()ing %s", fname);
   if (stat(sandbox_intern_string(fname), &st)==0 &&
       st.st_mtime < now-VERY_OLD_FILE_AGE) {
     char buf[ISO_TIME_LEN+1];

+ 2 - 0
src/or/dns.c

@@ -1480,6 +1480,7 @@ configure_nameservers(int force)
 
   evdns_set_log_fn(evdns_log_cb);
   if (conf_fname) {
+    log_debug(LD_FS, "stat()ing %s", conf_fname);
     if (stat(sandbox_intern_string(conf_fname), &st)) {
       log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s",
                conf_fname, strerror(errno));
@@ -1497,6 +1498,7 @@ configure_nameservers(int force)
 #if defined(DNS_OPTION_HOSTSFILE) && defined(USE_LIBSECCOMP)
     if (flags & DNS_OPTION_HOSTSFILE) {
       flags ^= DNS_OPTION_HOSTSFILE;
+      log_debug(LD_FS, "Loading /etc/hosts");
       evdns_base_load_hosts(the_evdns_base,
           sandbox_intern_string("/etc/hosts"));
     }

+ 117 - 50
src/or/main.c

@@ -2432,6 +2432,9 @@ tor_init(int argc, char *argv[])
     return -1;
   }
   stream_choice_seed_weak_rng();
+  if (tor_init_libevent_rng() < 0) {
+    log_warn(LD_NET, "Problem initializing libevent RNG.");
+  }
 
   return 0;
 }
@@ -2723,79 +2726,143 @@ init_addrinfo(void)
 static sandbox_cfg_t*
 sandbox_init_filter(void)
 {
+  const or_options_t *options = get_options();
   sandbox_cfg_t *cfg = sandbox_cfg_new();
+  int i;
 
   sandbox_cfg_allow_openat_filename(&cfg,
-      get_datadir_fname("cached-status"), 1);
+      get_datadir_fname("cached-status"));
 
   sandbox_cfg_allow_open_filename_array(&cfg,
-      get_datadir_fname("cached-certs"), 1,
-      get_datadir_fname("cached-certs.tmp"), 1,
-      get_datadir_fname("cached-consensus"), 1,
-      get_datadir_fname("unverified-consensus"), 1,
-      get_datadir_fname("unverified-consensus.tmp"), 1,
-      get_datadir_fname("cached-microdesc-consensus"), 1,
-      get_datadir_fname("cached-microdesc-consensus.tmp"), 1,
-      get_datadir_fname("cached-microdescs"), 1,
-      get_datadir_fname("cached-microdescs.tmp"), 1,
-      get_datadir_fname("cached-microdescs.new"), 1,
-      get_datadir_fname("cached-microdescs.new.tmp"), 1,
-      get_datadir_fname("unverified-microdesc-consensus"), 1,
-      get_datadir_fname("cached-descriptors"), 1,
-      get_datadir_fname("cached-descriptors.new"), 1,
-      get_datadir_fname("cached-descriptors.tmp"), 1,
-      get_datadir_fname("cached-descriptors.new.tmp"), 1,
-      get_datadir_fname("cached-descriptors.tmp.tmp"), 1,
-      get_datadir_fname("cached-extrainfo"), 1,
-      get_datadir_fname("state.tmp"), 1,
-      get_datadir_fname("unparseable-desc.tmp"), 1,
-      get_datadir_fname("unparseable-desc"), 1,
-      "/dev/srandom", 0,
-      "/dev/urandom", 0,
-      "/dev/random", 0,
+      get_datadir_fname("cached-certs"),
+      get_datadir_fname("cached-certs.tmp"),
+      get_datadir_fname("cached-consensus"),
+      get_datadir_fname("cached-consensus.tmp"),
+      get_datadir_fname("unverified-consensus"),
+      get_datadir_fname("unverified-consensus.tmp"),
+      get_datadir_fname("unverified-microdesc-consensus"),
+      get_datadir_fname("unverified-microdesc-consensus.tmp"),
+      get_datadir_fname("cached-microdesc-consensus"),
+      get_datadir_fname("cached-microdesc-consensus.tmp"),
+      get_datadir_fname("cached-microdescs"),
+      get_datadir_fname("cached-microdescs.tmp"),
+      get_datadir_fname("cached-microdescs.new"),
+      get_datadir_fname("cached-microdescs.new.tmp"),
+      get_datadir_fname("cached-descriptors"),
+      get_datadir_fname("cached-descriptors.new"),
+      get_datadir_fname("cached-descriptors.tmp"),
+      get_datadir_fname("cached-descriptors.new.tmp"),
+      get_datadir_fname("cached-descriptors.tmp.tmp"),
+      get_datadir_fname("cached-extrainfo"),
+      get_datadir_fname("cached-extrainfo.new"),
+      get_datadir_fname("cached-extrainfo.tmp"),
+      get_datadir_fname("cached-extrainfo.new.tmp"),
+      get_datadir_fname("cached-extrainfo.tmp.tmp"),
+      get_datadir_fname("state.tmp"),
+      get_datadir_fname("unparseable-desc.tmp"),
+      get_datadir_fname("unparseable-desc"),
+      get_datadir_fname("v3-status-votes"),
+      get_datadir_fname("v3-status-votes.tmp"),
+      tor_strdup("/dev/srandom"),
+      tor_strdup("/dev/urandom"),
+      tor_strdup("/dev/random"),
+      tor_strdup("/etc/hosts"),
       NULL, 0
   );
+  if (options->ServerDNSResolvConfFile)
+    sandbox_cfg_allow_open_filename(&cfg,
+                                tor_strdup(options->ServerDNSResolvConfFile));
+  else
+    sandbox_cfg_allow_open_filename(&cfg, tor_strdup("/etc/resolv.conf"));
+
+  for (i = 0; i < 2; ++i) {
+    if (get_torrc_fname(i)) {
+      sandbox_cfg_allow_open_filename(&cfg, tor_strdup(get_torrc_fname(i)));
+    }
+  }
+
+#define RENAME_SUFFIX(name, suffix)        \
+  sandbox_cfg_allow_rename(&cfg,           \
+      get_datadir_fname(name suffix),      \
+      get_datadir_fname(name))
+
+#define RENAME_SUFFIX2(prefix, name, suffix) \
+  sandbox_cfg_allow_rename(&cfg,                                        \
+                           get_datadir_fname2(prefix, name suffix),     \
+                           get_datadir_fname2(prefix, name))
+
+  RENAME_SUFFIX("cached-certs", ".tmp");
+  RENAME_SUFFIX("cached-consensus", ".tmp");
+  RENAME_SUFFIX("unverified-consensus", ".tmp");
+  RENAME_SUFFIX("unverified-microdesc-consensus", ".tmp");
+  RENAME_SUFFIX("cached-microdesc-consensus", ".tmp");
+  RENAME_SUFFIX("cached-microdescs", ".tmp");
+  RENAME_SUFFIX("cached-microdescs", ".new");
+  RENAME_SUFFIX("cached-microdescs.new", ".tmp");
+  RENAME_SUFFIX("cached-descriptors", ".tmp");
+  RENAME_SUFFIX("cached-descriptors", ".new");
+  RENAME_SUFFIX("cached-descriptors.new", ".tmp");
+  RENAME_SUFFIX("cached-extrainfo", ".tmp");
+  RENAME_SUFFIX("cached-extrainfo", ".new");
+  RENAME_SUFFIX("cached-extrainfo.new", ".tmp");
+  RENAME_SUFFIX("state", ".tmp");
+  RENAME_SUFFIX("unparseable-desc", ".tmp");
+  RENAME_SUFFIX("v3-status-votes", ".tmp");
 
   sandbox_cfg_allow_stat_filename_array(&cfg,
-      get_datadir_fname(NULL), 1,
-      get_datadir_fname("lock"), 1,
-      get_datadir_fname("state"), 1,
-      get_datadir_fname("router-stability"), 1,
-      get_datadir_fname("cached-extrainfo.new"), 1,
+      get_datadir_fname(NULL),
+      get_datadir_fname("lock"),
+      get_datadir_fname("state"),
+      get_datadir_fname("router-stability"),
+      get_datadir_fname("cached-extrainfo.new"),
       NULL, 0
   );
 
   // orport
   if (server_mode(get_options())) {
     sandbox_cfg_allow_open_filename_array(&cfg,
-        get_datadir_fname2("keys", "secret_id_key"), 1,
-        get_datadir_fname2("keys", "secret_onion_key"), 1,
-        get_datadir_fname2("keys", "secret_onion_key_ntor"), 1,
-        get_datadir_fname2("keys", "secret_onion_key_ntor.tmp"), 1,
-        get_datadir_fname2("keys", "secret_id_key.old"), 1,
-        get_datadir_fname2("keys", "secret_onion_key.old"), 1,
-        get_datadir_fname2("keys", "secret_onion_key_ntor.old"), 1,
-        get_datadir_fname2("keys", "secret_onion_key.tmp"), 1,
-        get_datadir_fname2("keys", "secret_id_key.tmp"), 1,
-        get_datadir_fname("fingerprint"), 1,
-        get_datadir_fname("fingerprint.tmp"), 1,
-        get_datadir_fname("hashed-fingerprint"), 1,
-        get_datadir_fname("hashed-fingerprint.tmp"), 1,
-        get_datadir_fname("cached-consensus"), 1,
-        get_datadir_fname("cached-consensus.tmp"), 1,
-        "/etc/resolv.conf", 0,
+        get_datadir_fname2("keys", "secret_id_key"),
+        get_datadir_fname2("keys", "secret_onion_key"),
+        get_datadir_fname2("keys", "secret_onion_key_ntor"),
+        get_datadir_fname2("keys", "secret_onion_key_ntor.tmp"),
+        get_datadir_fname2("keys", "secret_id_key.old"),
+        get_datadir_fname2("keys", "secret_onion_key.old"),
+        get_datadir_fname2("keys", "secret_onion_key_ntor.old"),
+        get_datadir_fname2("keys", "secret_onion_key.tmp"),
+        get_datadir_fname2("keys", "secret_id_key.tmp"),
+        get_datadir_fname("fingerprint"),
+        get_datadir_fname("fingerprint.tmp"),
+        get_datadir_fname("hashed-fingerprint"),
+        get_datadir_fname("hashed-fingerprint.tmp"),
+        get_datadir_fname("router-stability"),
+        get_datadir_fname("router-stability.tmp"),
+        tor_strdup("/etc/resolv.conf"),
         NULL, 0
     );
 
+    RENAME_SUFFIX("fingerprint", ".tmp");
+    RENAME_SUFFIX2("keys", "secret_onion_key_ntor", ".tmp");
+    RENAME_SUFFIX2("keys", "secret_id_key", ".tmp");
+    RENAME_SUFFIX2("keys", "secret_id_key.old", ".tmp");
+    RENAME_SUFFIX2("keys", "secret_onion_key", ".tmp");
+    RENAME_SUFFIX2("keys", "secret_onion_key.old", ".tmp");
+    RENAME_SUFFIX("hashed-fingerprint", ".tmp");
+    RENAME_SUFFIX("router-stability", ".tmp");
+
+    sandbox_cfg_allow_rename(&cfg,
+             get_datadir_fname2("keys", "secret_onion_key"),
+             get_datadir_fname2("keys", "secret_onion_key.old"));
+    sandbox_cfg_allow_rename(&cfg,
+             get_datadir_fname2("keys", "secret_onion_key_ntor"),
+             get_datadir_fname2("keys", "secret_onion_key_ntor.old"));
+
     sandbox_cfg_allow_stat_filename_array(&cfg,
-        get_datadir_fname("keys"), 1,
-        get_datadir_fname("stats/dirreq-stats"), 1,
+        get_datadir_fname("keys"),
+        get_datadir_fname("stats/dirreq-stats"),
         NULL, 0
     );
   }
 
-  sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor");
-
   init_addrinfo();
 
   return cfg;

+ 2 - 1
src/or/statefile.c

@@ -13,6 +13,7 @@
 #include "hibernate.h"
 #include "rephist.h"
 #include "router.h"
+#include "sandbox.h"
 #include "statefile.h"
 
 /** A list of state-file "abbreviations," for compatibility. */
@@ -285,7 +286,7 @@ or_state_save_broken(char *fname)
     log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
              "to \"%s\".  This could be a bug in Tor; please tell "
              "the developers.", fname, fname2);
-    if (rename(fname, fname2) < 0) {
+    if (tor_rename(fname, fname2) < 0) {//XXXX sandbox prohibits
       log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The "
                "OS gave an error of %s", strerror(errno));
     }