14 #ifndef _LARGEFILE64_SOURCE
19 #define _LARGEFILE64_SOURCE
29 #define MALLOC_MP_LIM (20*1024*1024)
44 #include "ext/tor_queue.h"
46 #include "ext/siphash.h"
48 #define DEBUGGING_CLOSE
50 #if defined(USE_LIBSECCOMP)
53 #include <sys/syscall.h>
54 #include <sys/types.h>
56 #include <sys/epoll.h>
57 #include <sys/prctl.h>
58 #include <linux/futex.h>
69 #ifdef HAVE_GNU_LIBC_VERSION_H
70 #include <gnu/libc-version.h>
72 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
73 #include <linux/netfilter_ipv4.h>
75 #ifdef HAVE_LINUX_IF_H
78 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
79 #include <linux/netfilter_ipv6/ip6_tables.h>
82 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
83 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
85 #define BACKTRACE_PRIVATE
98 #define REG_SYSCALL REG_EAX
99 #define M_SYSCALL gregs[REG_SYSCALL]
104 #elif defined(__x86_64__)
106 #define REG_SYSCALL REG_RAX
107 #define M_SYSCALL gregs[REG_SYSCALL]
109 #elif defined(__arm__)
111 #define M_SYSCALL arm_r7
113 #elif defined(__aarch64__) && defined(__LP64__)
115 #define REG_SYSCALL 8
116 #define M_SYSCALL regs[REG_SYSCALL]
121 #define SYSCALL_NAME_DEBUGGING
125 static int sandbox_active = 0;
130 #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
131 #define SCMP_CMP_STR(a,b,c) \
132 ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
133 #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
138 #define SCMP_CMP_MASKED(a,b,c) \
139 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
141 #define SCMP_CMP_NEG(a,op,b) (libc_negative_constant_needs_cast() ? \
142 (SCMP_CMP((a), (op), (unsigned int)(b))) : \
143 (SCMP_CMP_STR((a), (op), (b))))
148 static int filter_nopar_gen[] = {
151 SCMP_SYS(clock_gettime),
155 SCMP_SYS(epoll_create),
156 SCMP_SYS(epoll_wait),
157 #ifdef __NR_epoll_pwait
158 SCMP_SYS(epoll_pwait),
180 SCMP_SYS(getdents64),
182 #ifdef __NR_getegid32
186 #ifdef __NR_geteuid32
194 #ifdef __NR_getrlimit
197 SCMP_SYS(gettimeofday),
216 #ifdef __NR_nanosleep
222 #ifdef __NR_prlimit64
226 SCMP_SYS(rt_sigreturn),
227 SCMP_SYS(sched_getaffinity),
228 #ifdef __NR_sched_yield
229 SCMP_SYS(sched_yield),
232 SCMP_SYS(set_robust_list),
233 #ifdef __NR_setrlimit
237 #ifdef __NR_sigaltstack
238 SCMP_SYS(sigaltstack),
240 #ifdef __NR_sigreturn
248 SCMP_SYS(exit_group),
257 #ifdef __NR_getrandom
278 SCMP_SYS(getsockname),
280 #ifdef __NR_getpeername
281 SCMP_SYS(getpeername),
298 #define PHONY_OPENDIR_SYSCALL -2
302 #define seccomp_rule_add_0(ctx,act,call) \
303 seccomp_rule_add((ctx),(act),(call),0)
304 #define seccomp_rule_add_1(ctx,act,call,f1) \
305 seccomp_rule_add((ctx),(act),(call),1,(f1))
306 #define seccomp_rule_add_2(ctx,act,call,f1,f2) \
307 seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
308 #define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
309 seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
310 #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
311 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
313 static const char *sandbox_get_interned_string(
const char *str);
324 int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
325 SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS, SIGIO,
333 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
334 SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
351 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
352 SCMP_CMP(0, SCMP_CMP_EQ, 0));
369 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
370 SCMP_CMP(0, SCMP_CMP_EQ, 18));
376 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
377 SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
396 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
397 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
398 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
403 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
404 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
405 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
410 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
411 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
412 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
417 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
418 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
419 SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
424 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
425 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
426 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
431 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
432 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
433 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
438 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
439 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
440 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
449 #ifdef HAVE_GNU_LIBC_VERSION_H
450 #ifdef HAVE_GNU_GET_LIBC_VERSION
451 #define CHECK_LIBC_VERSION
458 is_libc_at_least(
int major,
int minor)
460 #ifdef CHECK_LIBC_VERSION
461 const char *version = gnu_get_libc_version();
468 tor_sscanf(version,
"%d.%d", &libc_major, &libc_minor);
469 if (libc_major > major)
471 else if (libc_major == major && libc_minor >= minor)
485 libc_uses_openat_for_open(
void)
487 return is_libc_at_least(2, 26);
493 libc_uses_openat_for_opendir(
void)
496 return is_libc_at_least(2, 27) ||
497 (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
503 libc_negative_constant_needs_cast(
void)
505 return is_libc_at_least(2, 27);
511 allow_file_open(scmp_filter_ctx ctx,
int use_openat,
const char *file)
514 return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
515 SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
516 SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
518 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
519 SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
533 int use_openat = libc_uses_openat_for_open();
536 for (elem = filter; elem != NULL; elem = elem->next) {
537 smp_param_t *param = elem->param;
539 if (param != NULL && param->prot == 1 && param->syscall
541 rc = allow_file_open(ctx, use_openat, param->value);
543 log_err(
LD_BUG,
"(Sandbox) failed to add open syscall, received "
544 "libseccomp error %d", rc);
560 for (elem = filter; elem != NULL; elem = elem->next) {
561 smp_param_t *param = elem->param;
563 if (param != NULL && param->prot == 1 && param->syscall
564 == SCMP_SYS(chmod)) {
565 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
566 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
568 log_err(
LD_BUG,
"(Sandbox) failed to add chmod syscall, received "
569 "libseccomp error %d", rc);
585 for (elem = filter; elem != NULL; elem = elem->next) {
586 smp_param_t *param = elem->param;
588 if (param != NULL && param->prot == 1 && param->syscall
589 == SCMP_SYS(chown)) {
590 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
591 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
593 log_err(
LD_BUG,
"(Sandbox) failed to add chown syscall, received "
594 "libseccomp error %d", rc);
614 for (elem = filter; elem != NULL; elem = elem->next) {
615 smp_param_t *param = elem->param;
617 if (param != NULL && param->prot == 1 &&
618 param->syscall == SCMP_SYS(rename)) {
620 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
621 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
622 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
624 log_err(
LD_BUG,
"(Sandbox) failed to add rename syscall, received "
625 "libseccomp error %d", rc);
645 for (elem = filter; elem != NULL; elem = elem->next) {
646 smp_param_t *param = elem->param;
648 if (param != NULL && param->prot == 1 && param->syscall
649 == SCMP_SYS(openat)) {
650 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
651 SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
652 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
653 SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
656 log_err(
LD_BUG,
"(Sandbox) failed to add openat syscall, received "
657 "libseccomp error %d", rc);
673 for (elem = filter; elem != NULL; elem = elem->next) {
674 smp_param_t *param = elem->param;
676 if (param != NULL && param->prot == 1 && param->syscall
677 == PHONY_OPENDIR_SYSCALL) {
678 rc = allow_file_open(ctx, libc_uses_openat_for_opendir(), param->value);
680 log_err(
LD_BUG,
"(Sandbox) failed to add openat syscall, received "
681 "libseccomp error %d", rc);
702 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
707 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
708 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
709 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
713 for (i = 0; i < 2; ++i) {
714 const int pf = i ? PF_INET : PF_INET6;
715 for (j=0; j < 3; ++j) {
716 const int type = (j == 0) ? SOCK_STREAM :
718 const int protocol = (j == 0) ? IPPROTO_TCP :
719 (j == 1) ? IPPROTO_IP :
721 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
722 SCMP_CMP(0, SCMP_CMP_EQ, pf),
723 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
724 SCMP_CMP(2, SCMP_CMP_EQ, protocol));
731 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
732 SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
733 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
734 SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
739 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
740 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
741 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
742 SCMP_CMP(2, SCMP_CMP_EQ, 0));
746 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
747 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
748 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
749 SCMP_CMP(2, SCMP_CMP_EQ, 0));
753 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
754 SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
755 SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
756 SCMP_CMP(2, SCMP_CMP_EQ, 0));
774 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
779 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
780 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
781 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
788 #ifdef HAVE_KIST_SUPPORT
790 #include <linux/sockios.h>
798 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
799 SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
818 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
823 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
824 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
825 SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
829 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
830 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
831 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
835 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
836 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
837 SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
842 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
843 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
844 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
849 #ifdef IP_TRANSPARENT
850 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
851 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
852 SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
858 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
859 SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
860 SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
879 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
884 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
885 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
886 SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
890 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
891 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
892 SCMP_CMP(2, SCMP_CMP_EQ, SO_ACCEPTCONN));
897 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
898 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
899 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
904 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
905 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
906 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
907 SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
912 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
913 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
914 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
915 SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
920 #ifdef HAVE_KIST_SUPPORT
921 #include <netinet/tcp.h>
922 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
923 SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
924 SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
943 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
944 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
948 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
949 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
950 SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
954 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
955 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
959 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
960 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
961 SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
981 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
982 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
986 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
987 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
991 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
992 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
1012 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1013 SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
1033 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1034 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
1038 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1039 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
1051 sb_rt_sigprocmask(scmp_filter_ctx ctx,
sandbox_cfg_t *filter)
1056 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1057 SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
1061 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1062 SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
1081 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1082 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
1086 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1087 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
1105 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1106 SCMP_CMP(1, SCMP_CMP_EQ,
1107 FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
1111 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1112 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
1116 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1117 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
1136 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
1137 SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
1156 for (elem = filter; elem != NULL; elem = elem->next) {
1157 smp_param_t *param = elem->param;
1159 if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1160 || param->syscall == SCMP_SYS(stat64))) {
1161 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
1162 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
1164 log_err(
LD_BUG,
"(Sandbox) failed to add stat64 syscall, received "
1165 "libseccomp error %d", rc);
1181 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill),
1182 SCMP_CMP(1, SCMP_CMP_EQ, 0));
1192 static sandbox_filter_func_t filter_func[] = {
1223 #ifdef HAVE_KIST_SUPPORT
1238 const char *interned = sandbox_get_interned_string(str);
1240 if (sandbox_active && str != NULL && interned == NULL) {
1241 log_warn(
LD_BUG,
"No interned sandbox parameter found for %s", str);
1244 return interned ? interned : str;
1252 sandbox_interned_string_is_missing(
const char *str)
1254 return sandbox_active && sandbox_get_interned_string(str) == NULL;
1263 sandbox_get_interned_string(
const char *str)
1270 for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
1271 smp_param_t *param = elem->param;
1274 if (!strcmp(str, (
char*)(param->value))) {
1275 return (
char*)param->value;
1277 if (param->value2 && !strcmp(str, (
char*)param->value2)) {
1278 return (
char*)param->value2;
1288 prot_strings_helper(strmap_t *locations,
1289 char **pr_mem_next_p,
1290 size_t *pr_mem_left_p,
1300 param_val = (
char*) *value_p;
1301 param_size = strlen(param_val) + 1;
1302 location = strmap_get(locations, param_val);
1307 *value_p = location;
1309 }
else if (*pr_mem_left_p >= param_size) {
1311 location = *pr_mem_next_p;
1312 memcpy(location, param_val, param_size);
1316 *value_p = location;
1318 strmap_set(locations, location, location);
1321 *pr_mem_next_p += param_size;
1322 *pr_mem_left_p -= param_size;
1325 log_err(
LD_BUG,
"(Sandbox) insufficient protected memory!");
1340 size_t pr_mem_size = 0, pr_mem_left = 0;
1341 char *pr_mem_next = NULL, *pr_mem_base;
1343 strmap_t *locations = NULL;
1346 for (el = cfg; el != NULL; el = el->next) {
1347 pr_mem_size += strlen((
char*) el->param->value) + 1;
1348 if (el->param->value2)
1349 pr_mem_size += strlen((
char*) el->param->value2) + 1;
1353 pr_mem_base = (
char*) mmap(NULL,
MALLOC_MP_LIM + pr_mem_size,
1354 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1355 if (pr_mem_base == MAP_FAILED) {
1356 log_err(
LD_BUG,
"(Sandbox) failed allocate protected memory! mmap: %s",
1363 pr_mem_left = pr_mem_size;
1365 locations = strmap_new();
1368 for (el = cfg; el != NULL; el = el->next) {
1369 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1370 &el->param->value) < 0) {
1374 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1375 &el->param->value2) < 0) {
1379 el->param->prot = 1;
1383 if (mprotect(pr_mem_base,
MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1384 log_err(
LD_BUG,
"(Sandbox) failed to protect memory! mprotect: %s",
1394 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
1395 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1397 log_err(
LD_BUG,
"(Sandbox) mremap protected memory filter fail!");
1402 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
1403 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1405 log_err(
LD_BUG,
"(Sandbox) munmap protected memory filter fail!");
1419 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1420 SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
1422 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1424 log_err(
LD_BUG,
"(Sandbox) mprotect protected memory filter fail (LT)!");
1428 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1429 SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
1432 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1434 log_err(
LD_BUG,
"(Sandbox) mprotect protected memory filter fail (GT)!");
1439 strmap_free(locations, NULL);
1450 new_element2(
int syscall,
char *value,
char *value2)
1452 smp_param_t *param = NULL;
1455 param = elem->param = tor_malloc_zero(
sizeof(smp_param_t));
1457 param->syscall = syscall;
1458 param->value = value;
1459 param->value2 = value2;
1466 new_element(
int syscall,
char *value)
1468 return new_element2(syscall, value, NULL);
1472 #define SCMP_stat SCMP_SYS(stat64)
1474 #define SCMP_stat SCMP_SYS(stat)
1482 elem = new_element(SCMP_stat, file);
1495 elem = new_element(SCMP_SYS(open), file);
1504 sandbox_cfg_allow_chmod_filename(
sandbox_cfg_t **cfg,
char *file)
1508 elem = new_element(SCMP_SYS(chmod), file);
1517 sandbox_cfg_allow_chown_filename(
sandbox_cfg_t **cfg,
char *file)
1521 elem = new_element(SCMP_SYS(chown), file);
1530 sandbox_cfg_allow_rename(
sandbox_cfg_t **cfg,
char *file1,
char *file2)
1534 elem = new_element2(SCMP_SYS(rename), file1, file2);
1547 elem = new_element(SCMP_SYS(openat), file);
1560 elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
1580 rc = filter_func[i](ctx, cfg);
1582 log_err(
LD_BUG,
"(Sandbox) failed to add syscall %d, received libseccomp "
1596 add_noparam_filter(scmp_filter_ctx ctx)
1603 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
1605 log_err(
LD_BUG,
"(Sandbox) failed to add syscall index %d (NR=%d), "
1606 "received libseccomp error %d", i, filter_nopar_gen[i], rc);
1611 if (is_libc_at_least(2, 33)) {
1612 #ifdef __NR_newfstatat
1624 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat));
1626 log_err(
LD_BUG,
"(Sandbox) failed to add newfstatat() syscall; "
1627 "received libseccomp error %d", rc);
1645 scmp_filter_ctx ctx;
1647 ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
1649 log_err(
LD_BUG,
"(Sandbox) failed to initialise libseccomp context");
1655 if ((rc = prot_strings(ctx, cfg))) {
1660 if ((rc = add_param_filter(ctx, cfg))) {
1661 log_err(
LD_BUG,
"(Sandbox) failed to add param filters!");
1666 if ((rc = add_noparam_filter(ctx))) {
1667 log_err(
LD_BUG,
"(Sandbox) failed to add param filters!");
1672 if ((rc = seccomp_load(ctx))) {
1673 log_err(
LD_BUG,
"(Sandbox) failed to load: %d (%s)! "
1674 "Are you sure that your kernel has seccomp2 support? The "
1675 "sandbox won't work without it.", rc,
1684 seccomp_release(ctx);
1685 return (rc < 0 ? -rc : rc);
1688 #ifdef SYSCALL_NAME_DEBUGGING
1689 #include "lib/sandbox/linux_syscalls.inc"
1693 get_syscall_name(
int syscall_num)
1696 for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
1697 if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
1698 return SYSCALLS_BY_NUMBER[i].syscall_name;
1702 static char syscall_name_buf[64];
1704 syscall_name_buf,
sizeof(syscall_name_buf));
1705 return syscall_name_buf;
1712 get_syscall_from_ucontext(
const ucontext_t *ctx)
1714 return (
int) ctx->uc_mcontext.M_SYSCALL;
1718 get_syscall_name(
int syscall_num)
1724 get_syscall_from_ucontext(
const ucontext_t *ctx)
1731 #ifdef USE_BACKTRACE
1732 #define MAX_DEPTH 256
1733 static void *syscall_cb_buf[MAX_DEPTH];
1742 sigsys_debugging(
int nr, siginfo_t *info,
void *void_context)
1744 ucontext_t *ctx = (ucontext_t *) (void_context);
1745 const char *syscall_name;
1746 #ifdef USE_BACKTRACE
1749 const int *fds = NULL;
1760 int syscall = get_syscall_from_ucontext(ctx);
1762 #ifdef USE_BACKTRACE
1763 depth = backtrace(syscall_cb_buf, MAX_DEPTH);
1766 clean_backtrace(syscall_cb_buf, depth, ctx);
1769 syscall_name = get_syscall_name(syscall);
1776 #ifdef USE_BACKTRACE
1778 for (i=0; i < n_fds; ++i)
1779 backtrace_symbols_fd(syscall_cb_buf, (
int)depth, fds[i]);
1782 #if defined(DEBUGGING_CLOSE)
1794 install_sigsys_debugging(
void)
1796 struct sigaction act;
1799 memset(&act, 0,
sizeof(act));
1801 sigaddset(&mask, SIGSYS);
1803 act.sa_sigaction = &sigsys_debugging;
1804 act.sa_flags = SA_SIGINFO;
1805 if (sigaction(SIGSYS, &act, NULL) < 0) {
1806 log_err(
LD_BUG,
"(Sandbox) Failed to register SIGSYS signal handler");
1810 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
1811 log_err(
LD_BUG,
"(Sandbox) Failed call to sigprocmask()");
1828 if (filter_dynamic == NULL) {
1829 filter_dynamic = cfg;
1833 for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
1843 #ifdef USE_LIBSECCOMP
1852 setenv(
"LIBC_FATAL_STDERR_",
"1", 1);
1854 if (install_sigsys_debugging())
1857 if (install_syscall_filter(cfg))
1860 if (register_cfg(cfg))
1869 return sandbox_active != 0;
1882 #if defined(USE_LIBSECCOMP)
1883 return initialise_libseccomp_sandbox(cfg);
1885 #elif defined(__linux__)
1888 "This version of Tor was built without support for sandboxing. To "
1889 "build with support for sandboxing on Linux, you must have "
1890 "libseccomp and its necessary header files (e.g. seccomp.h).");
1896 "Currently, sandboxing is only implemented on Linux. The feature "
1897 "is disabled on your platform.");
1902 #ifndef USE_LIBSECCOMP
1906 (void)cfg; (void)file;
1913 (void)cfg; (void)file;
1920 (void)cfg; (void)dir;
1927 (void)cfg; (void)file;
1932 sandbox_cfg_allow_chown_filename(
sandbox_cfg_t **cfg,
char *file)
1934 (void)cfg; (void)file;
1939 sandbox_cfg_allow_chmod_filename(
sandbox_cfg_t **cfg,
char *file)
1941 (void)cfg; (void)file;
1946 sandbox_cfg_allow_rename(
sandbox_cfg_t **cfg,
char *file1,
char *file2)
1948 (void)cfg; (void)file1; (void)file2;
Headers for util_malloc.c.
int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
int sandbox_init(sandbox_cfg_t *cfg)
int sandbox_is_active(void)
int sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
sandbox_cfg_t * sandbox_cfg_new(void)
int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
Header file for sandbox.c.
struct sandbox_cfg_elem_t sandbox_cfg_t
#define sandbox_intern_string(s)
int tor_sscanf(const char *buf, const char *pattern,...)
Definitions for timing-related constants.
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
void tor_log_err_sigsafe(const char *m,...)
int tor_log_get_sigsafe_err_fds(const int **out)
Integer definitions used throughout Tor.