aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/sandbox_fixes_1135113
-rw-r--r--configure.ac1
-rw-r--r--src/common/compat.c14
-rw-r--r--src/common/compat.h1
-rw-r--r--src/common/compat_libevent.c19
-rw-r--r--src/common/compat_libevent.h2
-rw-r--r--src/common/crypto.c1
-rwxr-xr-xsrc/common/gen_linux_syscalls.pl37
-rw-r--r--src/common/include.am1
-rw-r--r--src/common/linux_syscalls.inc1153
-rw-r--r--src/common/sandbox.c434
-rw-r--r--src/common/sandbox.h65
-rw-r--r--src/common/util.c2
-rw-r--r--src/or/config.c68
-rw-r--r--src/or/dns.c2
-rw-r--r--src/or/main.c167
-rw-r--r--src/or/statefile.c3
17 files changed, 1742 insertions, 241 deletions
diff --git a/changes/sandbox_fixes_11351 b/changes/sandbox_fixes_11351
new file mode 100644
index 000000000..2fe2173ce
--- /dev/null
+++ b/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.
+
diff --git a/configure.ac b/configure.ac
index 1f0675536..07b23dbcf 100644
--- a/configure.ac
+++ b/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>
diff --git a/src/common/compat.c b/src/common/compat.c
index 04c9d5923..c5945fbd2 100644
--- a/src/common/compat.c
+++ b/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
}
diff --git a/src/common/compat.h b/src/common/compat.h
index bb88818d8..9a381fb97 100644
--- a/src/common/compat.h
+++ b/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);
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 8525b4a72..74b54bb85 100644
--- a/src/common/compat_libevent.c
+++ b/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
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index f0d1828b7..9ee7b49cf 100644
--- a/src/common/compat_libevent.h
+++ b/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
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 8a4ffb694..a247a87d4 100644
--- a/src/common/crypto.c
+++ b/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]);
diff --git a/src/common/gen_linux_syscalls.pl b/src/common/gen_linux_syscalls.pl
new file mode 100755
index 000000000..3c64098a0
--- /dev/null
+++ b/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
diff --git a/src/common/include.am b/src/common/include.am
index d0ea40ea6..7b2465cd8 100644
--- a/src/common/include.am
+++ b/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 \
diff --git a/src/common/linux_syscalls.inc b/src/common/linux_syscalls.inc
new file mode 100644
index 000000000..912735660
--- /dev/null
+++ b/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}
+};
+
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index 0548f3edd..743d79ded 100644
--- a/src/common/sandbox.c
+++ b/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
diff --git a/src/common/sandbox.h b/src/common/sandbox.h
index d64d427d3..c40f5e0d1 100644
--- a/src/common/sandbox.h
+++ b/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_ */
diff --git a/src/common/util.c b/src/common/util.c
index a50f2566d..86bb8baae 100644
--- a/src/common/util.c
+++ b/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) {
diff --git a/src/or/config.c b/src/or/config.c
index b5827bee6..a5407dd4e 100644
--- a/src/or/config.c
+++ b/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];
diff --git a/src/or/dns.c b/src/or/dns.c
index 21c82e806..36271939b 100644
--- a/src/or/dns.c
+++ b/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"));
}
diff --git a/src/or/main.c b/src/or/main.c
index 0264064ed..4770b7e6d 100644
--- a/src/or/main.c
+++ b/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;
diff --git a/src/or/statefile.c b/src/or/statefile.c
index 2251f25e9..da3134171 100644
--- a/src/or/statefile.c
+++ b/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));
}