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>
58#include <linux/futex.h>
61#ifdef ENABLE_FRAGILE_HARDENING
62#include <sys/ptrace.h>
73#ifdef HAVE_GNU_LIBC_VERSION_H
74#include <gnu/libc-version.h>
76#ifdef HAVE_LINUX_NETFILTER_IPV4_H
77#include <linux/netfilter_ipv4.h>
82#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
83#include <linux/netfilter_ipv6/ip6_tables.h>
86#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
87 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
89#define BACKTRACE_PRIVATE
102#define REG_SYSCALL REG_EAX
103#define M_SYSCALL gregs[REG_SYSCALL]
108#elif defined(__x86_64__)
110#define REG_SYSCALL REG_RAX
111#define M_SYSCALL gregs[REG_SYSCALL]
113#elif defined(__arm__)
115#define M_SYSCALL arm_r7
117#elif defined(__aarch64__) && defined(__LP64__)
120#define M_SYSCALL regs[REG_SYSCALL]
125#define SYSCALL_NAME_DEBUGGING
133#if defined(__aarch64__) || defined(__riscv)
134#define ARCH_USES_GENERIC_SYSCALLS
138static int sandbox_active = 0;
143#define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
144#define SCMP_CMP_STR(a,b,c) \
145 ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
146#define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
151#define SCMP_CMP_MASKED(a,b,c) \
152 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
157#define SCMP_CMP_LOWER32_EQ(a,b) \
158 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b))
163static int filter_nopar_gen[] = {
166#ifdef __NR_clock_gettime64
167 SCMP_SYS(clock_gettime64),
169 SCMP_SYS(clock_gettime),
177 SCMP_SYS(epoll_create),
178 SCMP_SYS(epoll_wait),
179#ifdef __NR_epoll_pwait
180 SCMP_SYS(epoll_pwait),
202 SCMP_SYS(getdents64),
216#ifdef ENABLE_FRAGILE_HARDENING
222 SCMP_SYS(gettimeofday),
234#ifdef __NR_membarrier
236 SCMP_SYS(membarrier),
255 SCMP_SYS(rt_sigreturn),
259 SCMP_SYS(sched_getaffinity),
260#ifdef __NR_sched_yield
261 SCMP_SYS(sched_yield),
264 SCMP_SYS(set_robust_list),
269#ifdef __NR_sigaltstack
270 SCMP_SYS(sigaltstack),
275#if defined(__NR_stat)
277#elif defined(__i386__) && defined(__NR_statx)
284 SCMP_SYS(exit_group),
318 SCMP_SYS(getsockname),
320#ifdef __NR_getpeername
321 SCMP_SYS(getpeername),
338#define PHONY_OPENDIR_SYSCALL -2
342#define seccomp_rule_add_0(ctx,act,call) \
343 seccomp_rule_add((ctx),(act),(call),0)
344#define seccomp_rule_add_1(ctx,act,call,f1) \
345 seccomp_rule_add((ctx),(act),(call),1,(f1))
346#define seccomp_rule_add_2(ctx,act,call,f1,f2) \
347 seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
348#define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
349 seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
350#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
351 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
352#define seccomp_rule_add_5(ctx,act,call,f1,f2,f3,f4,f5) \
353 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4),(f5))
355static const char *sandbox_get_interned_string(
const char *str);
366 int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
367 SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS, SIGIO,
375 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
376 SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
394 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
395 SCMP_CMP(0, SCMP_CMP_EQ, 0));
410 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
411 SCMP_CMP(0, SCMP_CMP_EQ, 18));
417 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
418 SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
437 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
438 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
439 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
444 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
445 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
446 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
451 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
452 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
453 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
458 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
459 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
460 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
465 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
466 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
467 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
472 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
473 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
474 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
479 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
480 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
481 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
486 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
487 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
488 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
497#ifdef HAVE_GNU_LIBC_VERSION_H
498#ifdef HAVE_GNU_GET_LIBC_VERSION
499#define CHECK_LIBC_VERSION
506is_libc_at_least(
int major,
int minor)
508#ifdef CHECK_LIBC_VERSION
509 const char *version = gnu_get_libc_version();
516 tor_sscanf(version,
"%d.%d", &libc_major, &libc_minor);
517 if (libc_major > major)
519 else if (libc_major == major && libc_minor >= minor)
533libc_uses_openat_for_open(
void)
536 return is_libc_at_least(2, 26);
546#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
550libc_uses_openat_for_opendir(
void)
554 return is_libc_at_least(2, 27) ||
555 (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
566allow_file_open(scmp_filter_ctx ctx,
int use_openat,
const char *file)
569 return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
570 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
571 SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
573 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
574 SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
588 int use_openat = libc_uses_openat_for_open();
590#ifdef ENABLE_FRAGILE_HARDENING
596#ifdef ARCH_USES_GENERIC_SYSCALLS
597 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
598 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD));
600 log_err(
LD_BUG,
"(Sandbox) failed to add openat syscall, received "
601 "libseccomp error %d", rc);
610 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
612 log_err(
LD_BUG,
"(Sandbox) failed to add open syscall, received "
613 "libseccomp error %d", rc);
625 for (elem = filter; elem != NULL; elem = elem->next) {
626 smp_param_t *param = elem->param;
628 if (param != NULL && param->prot == 1 && param->syscall
630 rc = allow_file_open(ctx, use_openat, param->value);
632 log_err(
LD_BUG,
"(Sandbox) failed to add open syscall, received "
633 "libseccomp error %d", rc);
642#ifdef ARCH_USES_GENERIC_SYSCALLS
650 for (elem = filter; elem != NULL; elem = elem->next) {
651 smp_param_t *param = elem->param;
653 if (param != NULL && param->prot == 1 && param->syscall
654 == SCMP_SYS(fchmodat)) {
655 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
656 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
657 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
659 log_err(
LD_BUG,
"(Sandbox) failed to add fchmodat syscall, received "
660 "libseccomp error %d", rc);
676 for (elem = filter; elem != NULL; elem = elem->next) {
677 smp_param_t *param = elem->param;
679 if (param != NULL && param->prot == 1 && param->syscall
680 == SCMP_SYS(chmod)) {
681 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
682 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
684 log_err(
LD_BUG,
"(Sandbox) failed to add chmod syscall, received "
685 "libseccomp error %d", rc);
695#if defined(ARCH_USES_GENERIC_SYSCALLS)
703 for (elem = filter; elem != NULL; elem = elem->next) {
704 smp_param_t *param = elem->param;
706 if (param != NULL && param->prot == 1 && param->syscall
707 == SCMP_SYS(fchownat)) {
708 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
709 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
710 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
712 log_err(
LD_BUG,
"(Sandbox) failed to add fchownat syscall, received "
713 "libseccomp error %d", rc);
721#elif defined(__i386__)
729 for (elem = filter; elem != NULL; elem = elem->next) {
730 smp_param_t *param = elem->param;
732 if (param != NULL && param->prot == 1 && param->syscall
733 == SCMP_SYS(chown32)) {
734 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown32),
735 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
737 log_err(
LD_BUG,
"(Sandbox) failed to add chown32 syscall, received "
738 "libseccomp error %d", rc);
754 for (elem = filter; elem != NULL; elem = elem->next) {
755 smp_param_t *param = elem->param;
757 if (param != NULL && param->prot == 1 && param->syscall
758 == SCMP_SYS(chown)) {
759 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
760 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
762 log_err(
LD_BUG,
"(Sandbox) failed to add chown syscall, received "
763 "libseccomp error %d", rc);
773#if defined(__NR_rename)
785 for (elem = filter; elem != NULL; elem = elem->next) {
786 smp_param_t *param = elem->param;
788 if (param != NULL && param->prot == 1 &&
789 param->syscall == SCMP_SYS(rename)) {
791 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
792 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
793 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
795 log_err(
LD_BUG,
"(Sandbox) failed to add rename syscall, received "
796 "libseccomp error %d", rc);
804#elif defined(__NR_renameat)
816 for (elem = filter; elem != NULL; elem = elem->next) {
817 smp_param_t *param = elem->param;
819 if (param != NULL && param->prot == 1 &&
820 param->syscall == SCMP_SYS(renameat)) {
822 rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
823 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
824 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
825 SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
826 SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
828 log_err(
LD_BUG,
"(Sandbox) failed to add renameat syscall, received "
829 "libseccomp error %d", rc);
849 for (elem = filter; elem != NULL; elem = elem->next) {
850 smp_param_t *param = elem->param;
852 if (param != NULL && param->prot == 1 &&
853 param->syscall == SCMP_SYS(renameat2)) {
855 rc = seccomp_rule_add_5(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat2),
856 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
857 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
858 SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
859 SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2),
860 SCMP_CMP(4, SCMP_CMP_EQ, 0));
862 log_err(
LD_BUG,
"(Sandbox) failed to add renameat2 syscall, received "
863 "libseccomp error %d", rc);
883#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
895 for (elem = filter; elem != NULL; elem = elem->next) {
896 smp_param_t *param = elem->param;
898 if (param != NULL && param->prot == 1 && param->syscall
899 == SCMP_SYS(openat)) {
900 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
901 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
902 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
903 SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
906 log_err(
LD_BUG,
"(Sandbox) failed to add openat syscall, received "
907 "libseccomp error %d", rc);
923 for (elem = filter; elem != NULL; elem = elem->next) {
924 smp_param_t *param = elem->param;
926 if (param != NULL && param->prot == 1 && param->syscall
927 == PHONY_OPENDIR_SYSCALL) {
928 rc = allow_file_open(ctx, libc_uses_openat_for_opendir(), param->value);
930 log_err(
LD_BUG,
"(Sandbox) failed to add openat syscall, received "
931 "libseccomp error %d", rc);
942#ifdef ENABLE_FRAGILE_HARDENING
951 pid_t pid = getpid();
954 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
955 SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_ATTACH),
956 SCMP_CMP(1, SCMP_CMP_EQ, pid));
962#if defined(__aarch64__) || defined(__s390__)
963 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
964 SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGSET),
965 SCMP_CMP(1, SCMP_CMP_EQ, pid));
967 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
968 SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
969 SCMP_CMP(1, SCMP_CMP_EQ, pid));
990 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
995 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
996 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
997 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
1001 for (i = 0; i < 2; ++i) {
1002 const int pf = i ? PF_INET : PF_INET6;
1003 for (j=0; j < 3; ++j) {
1004 const int type = (j == 0) ? SOCK_STREAM :
1006 const int protocol = (j == 0) ? IPPROTO_TCP :
1007 (j == 1) ? IPPROTO_IP :
1009 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1010 SCMP_CMP(0, SCMP_CMP_EQ, pf),
1011 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
1012 SCMP_CMP(2, SCMP_CMP_EQ, protocol));
1019 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1020 SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
1021 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
1022 SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
1027 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1028 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
1029 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
1030 SCMP_CMP(2, SCMP_CMP_EQ, 0));
1034 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1035 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
1036 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
1037 SCMP_CMP(2, SCMP_CMP_EQ, 0));
1041 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1042 SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
1043 SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
1044 SCMP_CMP(2, SCMP_CMP_EQ, 0));
1062 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
1067 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
1068 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
1069 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
1076#ifdef HAVE_KIST_SUPPORT
1078#include <linux/sockios.h>
1086 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
1087 SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
1106 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
1111 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1112 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1113 SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
1117 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1118 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1119 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
1123 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1124 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1125 SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
1130 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1131 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1132 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
1137#ifdef IP_TRANSPARENT
1138 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1139 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1140 SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
1146 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1147 SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
1148 SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
1153#ifdef IP_BIND_ADDRESS_NO_PORT
1154 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1155 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1156 SCMP_CMP(2, SCMP_CMP_EQ, IP_BIND_ADDRESS_NO_PORT));
1175 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
1180 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1181 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1182 SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
1186 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1187 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1188 SCMP_CMP(2, SCMP_CMP_EQ, SO_ACCEPTCONN));
1193 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1194 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1195 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
1200#ifdef HAVE_LINUX_NETFILTER_IPV4_H
1201 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1202 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1203 SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
1208#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
1209 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1210 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
1211 SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
1216#ifdef HAVE_KIST_SUPPORT
1217#include <netinet/tcp.h>
1218 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1219 SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
1220 SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
1239 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1240 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
1244 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1245 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
1246 SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
1250 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1251 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
1255 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1256 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
1257 SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
1277 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1278 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
1282 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1283 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
1287 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1288 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
1308#ifdef ENABLE_FRAGILE_HARDENING
1309 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1310 SCMP_CMP(0, SCMP_CMP_EQ, PR_GET_DUMPABLE));
1314 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1315 SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PTRACER));
1320 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1321 SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
1341 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1342 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
1346 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1347 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
1359sb_rt_sigprocmask(scmp_filter_ctx ctx,
sandbox_cfg_t *filter)
1364#if defined(ENABLE_FRAGILE_HARDENING) || \
1365 defined(USE_TRACING_INSTRUMENTATION_LTTNG)
1366 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1367 SCMP_CMP(0, SCMP_CMP_EQ, SIG_BLOCK));
1372 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1373 SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
1377 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1378 SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
1397 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1398 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
1402 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1403 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
1421 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1422 SCMP_CMP(1, SCMP_CMP_EQ,
1423 FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
1427 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1428 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
1432 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1433 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
1452 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
1453 SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
1460#ifdef ARCH_USES_GENERIC_SYSCALLS
1473 for (elem = filter; elem != NULL; elem = elem->next) {
1474 smp_param_t *param = elem->param;
1476 if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1477 || param->syscall == PHONY_OPENDIR_SYSCALL
1478 || param->syscall == SCMP_SYS(newfstatat))) {
1479 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat),
1480 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
1481 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
1483 log_err(
LD_BUG,
"(Sandbox) failed to add newfstatat syscall, received "
1484 "libseccomp error %d", rc);
1506 for (elem = filter; elem != NULL; elem = elem->next) {
1507 smp_param_t *param = elem->param;
1509 if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1510 || param->syscall == SCMP_SYS(stat64))) {
1511 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
1512 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
1514 log_err(
LD_BUG,
"(Sandbox) failed to add stat64 syscall, received "
1515 "libseccomp error %d", rc);
1531 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill),
1532 SCMP_CMP(1, SCMP_CMP_EQ, 0));
1542static sandbox_filter_func_t filter_func[] = {
1552#if defined(ARCH_USES_GENERIC_SYSCALLS)
1554#elif defined(__i386__)
1559#if defined(ARCH_USES_GENERIC_SYSCALLS)
1565#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
1569#ifdef ENABLE_FRAGILE_HARDENING
1572#if defined(__NR_rename)
1574#elif defined(__NR_renameat)
1588#if defined(ARCH_USES_GENERIC_SYSCALLS)
1590#elif defined(__NR_stat64)
1598#ifdef HAVE_KIST_SUPPORT
1613 const char *interned = sandbox_get_interned_string(str);
1615 if (sandbox_active && str != NULL && interned == NULL) {
1616 log_warn(
LD_BUG,
"No interned sandbox parameter found for %s", str);
1619 return interned ? interned : str;
1627sandbox_interned_string_is_missing(
const char *str)
1629 return sandbox_active && sandbox_get_interned_string(str) == NULL;
1638sandbox_get_interned_string(
const char *str)
1645 for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
1646 smp_param_t *param = elem->param;
1649 if (!strcmp(str, (
char*)(param->value))) {
1650 return (
char*)param->value;
1652 if (param->value2 && !strcmp(str, (
char*)param->value2)) {
1653 return (
char*)param->value2;
1663prot_strings_helper(strmap_t *locations,
1664 char **pr_mem_next_p,
1665 size_t *pr_mem_left_p,
1675 param_val = (
char*) *value_p;
1676 param_size = strlen(param_val) + 1;
1677 location = strmap_get(locations, param_val);
1682 *value_p = location;
1684 }
else if (*pr_mem_left_p >= param_size) {
1686 location = *pr_mem_next_p;
1687 memcpy(location, param_val, param_size);
1691 *value_p = location;
1693 strmap_set(locations, location, location);
1696 *pr_mem_next_p += param_size;
1697 *pr_mem_left_p -= param_size;
1700 log_err(
LD_BUG,
"(Sandbox) insufficient protected memory!");
1715 size_t pr_mem_size = 0, pr_mem_left = 0;
1716 char *pr_mem_next = NULL, *pr_mem_base;
1718 strmap_t *locations = NULL;
1721 for (el = cfg; el != NULL; el = el->next) {
1722 pr_mem_size += strlen((
char*) el->param->value) + 1;
1723 if (el->param->value2)
1724 pr_mem_size += strlen((
char*) el->param->value2) + 1;
1728 pr_mem_base = (
char*) mmap(NULL,
MALLOC_MP_LIM + pr_mem_size,
1729 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1730 if (pr_mem_base == MAP_FAILED) {
1731 log_err(
LD_BUG,
"(Sandbox) failed allocate protected memory! mmap: %s",
1738 pr_mem_left = pr_mem_size;
1740 locations = strmap_new();
1743 for (el = cfg; el != NULL; el = el->next) {
1744 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1745 &el->param->value) < 0) {
1749 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1750 &el->param->value2) < 0) {
1754 el->param->prot = 1;
1758 if (mprotect(pr_mem_base,
MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1759 log_err(
LD_BUG,
"(Sandbox) failed to protect memory! mprotect: %s",
1769 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
1770 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1772 log_err(
LD_BUG,
"(Sandbox) mremap protected memory filter fail!");
1777 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
1778 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1780 log_err(
LD_BUG,
"(Sandbox) munmap protected memory filter fail!");
1794 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1795 SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
1797 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1799 log_err(
LD_BUG,
"(Sandbox) mprotect protected memory filter fail (LT)!");
1803 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1804 SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
1807 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1809 log_err(
LD_BUG,
"(Sandbox) mprotect protected memory filter fail (GT)!");
1814 strmap_free(locations, NULL);
1825new_element2(
int syscall,
char *value,
char *value2)
1827 smp_param_t *param = NULL;
1830 param = elem->param = tor_malloc_zero(
sizeof(smp_param_t));
1832 param->syscall = syscall;
1833 param->value = value;
1834 param->value2 = value2;
1841new_element(
int syscall,
char *value)
1843 return new_element2(syscall, value, NULL);
1846#if defined(ARCH_USES_GENERIC_SYSCALLS)
1847#define SCMP_chown SCMP_SYS(fchownat)
1848#elif defined(__i386__)
1849#define SCMP_chown SCMP_SYS(chown32)
1851#define SCMP_chown SCMP_SYS(chown)
1854#if defined(ARCH_USES_GENERIC_SYSCALLS)
1855#define SCMP_chmod SCMP_SYS(fchmodat)
1857#define SCMP_chmod SCMP_SYS(chmod)
1860#if defined(__NR_rename)
1861#define SCMP_rename SCMP_SYS(rename)
1862#elif defined(__NR_renameat)
1863#define SCMP_rename SCMP_SYS(renameat)
1865#define SCMP_rename SCMP_SYS(renameat2)
1868#if defined(ARCH_USES_GENERIC_SYSCALLS)
1869#define SCMP_stat SCMP_SYS(newfstatat)
1870#elif defined(__NR_stat64)
1871#define SCMP_stat SCMP_SYS(stat64)
1873#define SCMP_stat SCMP_SYS(stat)
1881 elem = new_element(SCMP_stat, file);
1894 elem = new_element(SCMP_SYS(open), file);
1903sandbox_cfg_allow_chmod_filename(
sandbox_cfg_t **cfg,
char *file)
1907 elem = new_element(SCMP_chmod, file);
1916sandbox_cfg_allow_chown_filename(
sandbox_cfg_t **cfg,
char *file)
1920 elem = new_element(SCMP_chown, file);
1929sandbox_cfg_allow_rename(
sandbox_cfg_t **cfg,
char *file1,
char *file2)
1933 elem = new_element2(SCMP_rename, file1, file2);
1946 elem = new_element(SCMP_SYS(openat), file);
1959 elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
1979 rc = filter_func[i](ctx, cfg);
1981 log_err(
LD_BUG,
"(Sandbox) failed to add syscall %d, received libseccomp "
1995add_noparam_filter(scmp_filter_ctx ctx)
2002 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
2004 log_err(
LD_BUG,
"(Sandbox) failed to add syscall index %d (NR=%d), "
2005 "received libseccomp error %d", i, filter_nopar_gen[i], rc);
2010 if (is_libc_at_least(2, 33)) {
2011#ifdef __NR_newfstatat
2023 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat));
2025 log_err(
LD_BUG,
"(Sandbox) failed to add newfstatat() syscall; "
2026 "received libseccomp error %d", rc);
2029#elif defined(__NR_fstatat64)
2032 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstatat64));
2034 log_err(
LD_BUG,
"(Sandbox) failed to add fstatat64() syscall; "
2035 "received libseccomp error %d", rc);
2039#if defined(__i386__) && defined(__NR_statx)
2042 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statx));
2044 log_err(
LD_BUG,
"(Sandbox) failed to add statx() syscall; "
2045 "received libseccomp error %d", rc);
2063 scmp_filter_ctx ctx;
2065 ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
2067 log_err(
LD_BUG,
"(Sandbox) failed to initialise libseccomp context");
2073 if ((rc = prot_strings(ctx, cfg))) {
2078 if ((rc = add_param_filter(ctx, cfg))) {
2079 log_err(
LD_BUG,
"(Sandbox) failed to add param filters!");
2084 if ((rc = add_noparam_filter(ctx))) {
2085 log_err(
LD_BUG,
"(Sandbox) failed to add param filters!");
2090 if ((rc = seccomp_load(ctx))) {
2091 log_err(
LD_BUG,
"(Sandbox) failed to load: %d (%s)! "
2092 "Are you sure that your kernel has seccomp2 support? The "
2093 "sandbox won't work without it.", rc,
2102 seccomp_release(ctx);
2103 return (rc < 0 ? -rc : rc);
2106#ifdef SYSCALL_NAME_DEBUGGING
2107#include "lib/sandbox/linux_syscalls.inc"
2111get_syscall_name(
int syscall_num)
2114 for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
2115 if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
2116 return SYSCALLS_BY_NUMBER[i].syscall_name;
2120 static char syscall_name_buf[64];
2122 syscall_name_buf,
sizeof(syscall_name_buf));
2123 return syscall_name_buf;
2130get_syscall_from_ucontext(
const ucontext_t *ctx)
2132 return (
int) ctx->uc_mcontext.M_SYSCALL;
2136get_syscall_name(
int syscall_num)
2142get_syscall_from_ucontext(
const ucontext_t *ctx)
2150#define MAX_DEPTH 256
2151static void *syscall_cb_buf[MAX_DEPTH];
2160sigsys_debugging(
int nr, siginfo_t *info,
void *void_context)
2162 ucontext_t *ctx = (ucontext_t *) (void_context);
2163 const char *syscall_name;
2167 const int *fds = NULL;
2178 int syscall = get_syscall_from_ucontext(ctx);
2181 depth = backtrace(syscall_cb_buf, MAX_DEPTH);
2184 clean_backtrace(syscall_cb_buf, depth, ctx);
2187 syscall_name = get_syscall_name(syscall);
2196 for (i=0; i < n_fds; ++i)
2197 backtrace_symbols_fd(syscall_cb_buf, (
int)depth, fds[i]);
2200#if defined(DEBUGGING_CLOSE)
2212install_sigsys_debugging(
void)
2214 struct sigaction act;
2217 memset(&act, 0,
sizeof(act));
2219 sigaddset(&mask, SIGSYS);
2221 act.sa_sigaction = &sigsys_debugging;
2222 act.sa_flags = SA_SIGINFO;
2223 if (sigaction(SIGSYS, &act, NULL) < 0) {
2224 log_err(
LD_BUG,
"(Sandbox) Failed to register SIGSYS signal handler");
2228 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
2229 log_err(
LD_BUG,
"(Sandbox) Failed call to sigprocmask()");
2246 if (filter_dynamic == NULL) {
2247 filter_dynamic = cfg;
2251 for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
2261#ifdef USE_LIBSECCOMP
2270 setenv(
"LIBC_FATAL_STDERR_",
"1", 1);
2272 if (install_sigsys_debugging())
2275 if (install_syscall_filter(cfg))
2278 if (register_cfg(cfg))
2287 return sandbox_active != 0;
2300#if defined(USE_LIBSECCOMP)
2301 return initialise_libseccomp_sandbox(cfg);
2303#elif defined(__linux__)
2306 "This version of Tor was built without support for sandboxing. To "
2307 "build with support for sandboxing on Linux, you must have "
2308 "libseccomp and its necessary header files (e.g. seccomp.h).");
2314 "Currently, sandboxing is only implemented on Linux. The feature "
2315 "is disabled on your platform.");
2320#ifndef USE_LIBSECCOMP
2324 (void)cfg; (void)file;
2331 (void)cfg; (void)file;
2338 (void)cfg; (void)dir;
2345 (void)cfg; (void)file;
2350sandbox_cfg_allow_chown_filename(
sandbox_cfg_t **cfg,
char *file)
2352 (void)cfg; (void)file;
2357sandbox_cfg_allow_chmod_filename(
sandbox_cfg_t **cfg,
char *file)
2359 (void)cfg; (void)file;
2364sandbox_cfg_allow_rename(
sandbox_cfg_t **cfg,
char *file1,
char *file2)
2366 (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)
sandbox_cfg_t * sandbox_cfg_new(void)
int sandbox_init(sandbox_cfg_t *cfg)
int sandbox_is_active(void)
int sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
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.