1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to enable sandboxing.
14 #ifndef _LARGEFILE64_SOURCE
16 * Temporarily required for O_LARGEFILE flag. Needs to be removed
17 * with the libevent fix.
19 #define _LARGEFILE64_SOURCE
20 #endif /* !defined(_LARGEFILE64_SOURCE) */
22 /** Malloc mprotect limit in bytes.
24 * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
25 * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
26 * liblzma have a small overhead that we need to compensate for to avoid being
27 * killed by the sandbox.
29 #define MALLOC_MP_LIM (20*1024*1024)
36 #include "lib/sandbox/sandbox.h"
37 #include "lib/container/map.h"
38 #include "lib/err/torerr.h"
39 #include "lib/log/log.h"
40 #include "lib/cc/torint.h"
41 #include "lib/malloc/malloc.h"
42 #include "lib/string/scanf.h"
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>
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>
79 #ifdef HAVE_LINUX_IF_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
90 #include "lib/err/backtrace.h"
91 #endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
98 * Linux 32 bit definitions
100 #if defined(__i386__)
102 #define REG_SYSCALL REG_EAX
103 #define M_SYSCALL gregs[REG_SYSCALL]
106 * Linux 64 bit definitions
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__)
119 #define REG_SYSCALL 8
120 #define M_SYSCALL regs[REG_SYSCALL]
122 #endif /* defined(__i386__) || ... */
125 #define SYSCALL_NAME_DEBUGGING
128 /**Determines if at least one sandbox is active.*/
129 static int sandbox_active
= 0;
130 /** Holds the parameter list configuration for the sandbox.*/
131 static sandbox_cfg_t
*filter_dynamic
= NULL
;
134 #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
135 #define SCMP_CMP_STR(a,b,c) \
136 ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
137 #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
138 /* We use a wrapper here because these masked comparisons seem to be pretty
139 * verbose. Also, it's important to cast to scmp_datum_t before negating the
140 * mask, since otherwise the negation might get applied to a 32 bit value, and
141 * the high bits of the value might get masked out improperly. */
142 #define SCMP_CMP_MASKED(a,b,c) \
143 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
144 /* Negative constants aren't consistently sign extended or zero extended.
145 * Different compilers, libc, and architectures behave differently. For cases
146 * where the kernel ABI uses a 32 bit integer, this macro can be used to
147 * mask-compare only the lower 32 bits of the value. */
148 #define SCMP_CMP_LOWER32_EQ(a,b) \
149 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b))
151 /** Variable used for storing all syscall numbers that will be allowed with the
152 * stage 1 general Tor sandbox.
154 static int filter_nopar_gen
[] = {
157 #ifdef __NR_clock_gettime64
158 SCMP_SYS(clock_gettime64
),
160 SCMP_SYS(clock_gettime
),
168 SCMP_SYS(epoll_create
),
169 SCMP_SYS(epoll_wait
),
170 #ifdef __NR_epoll_pwait
171 SCMP_SYS(epoll_pwait
),
193 SCMP_SYS(getdents64
),
195 #ifdef __NR_getegid32
199 #ifdef __NR_geteuid32
207 #ifdef ENABLE_FRAGILE_HARDENING
210 #ifdef __NR_getrlimit
213 SCMP_SYS(gettimeofday
),
228 /* XXXX restrict this in the same ways as mmap2 */
232 #ifdef __NR_nanosleep
238 #ifdef __NR_prlimit64
242 SCMP_SYS(rt_sigreturn
),
246 SCMP_SYS(sched_getaffinity
),
247 #ifdef __NR_sched_yield
248 SCMP_SYS(sched_yield
),
251 SCMP_SYS(set_robust_list
),
252 #ifdef __NR_setrlimit
256 #ifdef __NR_sigaltstack
257 SCMP_SYS(sigaltstack
),
259 #ifdef __NR_sigreturn
263 #if defined(__i386__) && defined(__NR_statx)
270 SCMP_SYS(exit_group
),
275 // getaddrinfo uses this..
279 #ifdef __NR_getrandom
288 * These socket syscalls are not required on x86_64 and not supported with
289 * some libseccomp versions (eg: 1.0.1)
300 SCMP_SYS(getsockname
),
302 #ifdef __NR_getpeername
303 SCMP_SYS(getpeername
),
316 /* opendir is not a syscall but it will use either open or openat. We do not
317 * want the decision to allow open/openat to be the callers reponsability, so
318 * we create a phony syscall number for opendir and sb_opendir will choose the
319 * correct syscall. */
320 #define PHONY_OPENDIR_SYSCALL -2
322 /* These macros help avoid the error where the number of filters we add on a
323 * single rule don't match the arg_cnt param. */
324 #define seccomp_rule_add_0(ctx,act,call) \
325 seccomp_rule_add((ctx),(act),(call),0)
326 #define seccomp_rule_add_1(ctx,act,call,f1) \
327 seccomp_rule_add((ctx),(act),(call),1,(f1))
328 #define seccomp_rule_add_2(ctx,act,call,f1,f2) \
329 seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
330 #define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
331 seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
332 #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
333 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
335 static const char *sandbox_get_interned_string(const char *str
);
338 * Function responsible for setting up the rt_sigaction syscall for
339 * the seccomp filter sandbox.
342 sb_rt_sigaction(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
346 int param
[] = { SIGINT
, SIGTERM
, SIGPIPE
, SIGUSR1
, SIGUSR2
, SIGHUP
, SIGCHLD
,
347 SIGSEGV
, SIGILL
, SIGFPE
, SIGBUS
, SIGSYS
, SIGIO
,
354 for (i
= 0; i
< ARRAY_LENGTH(param
); i
++) {
355 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigaction
),
356 SCMP_CMP(0, SCMP_CMP_EQ
, param
[i
]));
366 * Function responsible for setting up the time syscall for
367 * the seccomp filter sandbox.
370 sb_time(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
374 return seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(time
),
375 SCMP_CMP(0, SCMP_CMP_EQ
, 0));
377 #endif /* defined(__NR_time) */
380 * Function responsible for setting up the accept4 syscall for
381 * the seccomp filter sandbox.
384 sb_accept4(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
390 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketcall
),
391 SCMP_CMP(0, SCMP_CMP_EQ
, 18));
395 #endif /* defined(__i386__) */
397 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(accept4
),
398 SCMP_CMP_MASKED(3, SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0));
408 * Function responsible for setting up the mmap2 syscall for
409 * the seccomp filter sandbox.
412 sb_mmap2(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
417 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
418 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
),
419 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
));
424 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
425 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_NONE
),
426 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_ANONYMOUS
|MAP_NORESERVE
));
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_ANONYMOUS
));
438 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
439 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
440 SCMP_CMP(3, SCMP_CMP_EQ
,MAP_PRIVATE
|MAP_ANONYMOUS
|MAP_STACK
));
445 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
446 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
447 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_FIXED
|MAP_DENYWRITE
));
452 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
453 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
454 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_FIXED
|MAP_ANONYMOUS
));
459 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
460 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_EXEC
),
461 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_DENYWRITE
));
468 #endif /* defined(__NR_mmap2) */
470 #ifdef HAVE_GNU_LIBC_VERSION_H
471 #ifdef HAVE_GNU_GET_LIBC_VERSION
472 #define CHECK_LIBC_VERSION
476 /* Return true the libc version is greater or equal than
477 * <b>major</b>.<b>minor</b>. Returns false otherwise. */
479 is_libc_at_least(int major
, int minor
)
481 #ifdef CHECK_LIBC_VERSION
482 const char *version
= gnu_get_libc_version();
489 tor_sscanf(version
, "%d.%d", &libc_major
, &libc_minor
);
490 if (libc_major
> major
)
492 else if (libc_major
== major
&& libc_minor
>= minor
)
496 #else /* !defined(CHECK_LIBC_VERSION) */
500 #endif /* defined(CHECK_LIBC_VERSION) */
503 /* Return true if we think we're running with a libc that uses openat for the
504 * open function on linux. */
506 libc_uses_openat_for_open(void)
508 return is_libc_at_least(2, 26);
511 /* Return true if we think we're running with a libc that uses openat for the
512 * opendir function on linux. */
514 libc_uses_openat_for_opendir(void)
516 // libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
517 return is_libc_at_least(2, 27) ||
518 (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
521 /** Allow a single file to be opened. If <b>use_openat</b> is true,
522 * we're using a libc that remaps all the opens into openats. */
524 allow_file_open(scmp_filter_ctx ctx
, int use_openat
, const char *file
)
527 return seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(openat
),
528 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD
),
529 SCMP_CMP_STR(1, SCMP_CMP_EQ
, file
));
531 return seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(open
),
532 SCMP_CMP_STR(0, SCMP_CMP_EQ
, file
));
537 * Function responsible for setting up the open syscall for
538 * the seccomp filter sandbox.
541 sb_open(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
544 sandbox_cfg_t
*elem
= NULL
;
546 int use_openat
= libc_uses_openat_for_open();
548 #ifdef ENABLE_FRAGILE_HARDENING
549 /* AddressSanitizer uses the "open" syscall to access information about the
550 * running process via the filesystem, so that call must be allowed without
551 * restriction or the sanitizer will be unable to execute normally when the
552 * process terminates. */
553 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(open
));
555 log_err(LD_BUG
,"(Sandbox) failed to add open syscall, received "
556 "libseccomp error %d", rc
);
560 /* If glibc also uses only the "open" syscall to open files on this system
561 * there is no need to consider any additional rules. */
566 // for each dynamic parameter filters
567 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
568 smp_param_t
*param
= elem
->param
;
570 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
572 rc
= allow_file_open(ctx
, use_openat
, param
->value
);
574 log_err(LD_BUG
,"(Sandbox) failed to add open syscall, received "
575 "libseccomp error %d", rc
);
585 sb_chmod(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
588 sandbox_cfg_t
*elem
= NULL
;
590 // for each dynamic parameter filters
591 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
592 smp_param_t
*param
= elem
->param
;
594 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
595 == SCMP_SYS(chmod
)) {
596 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(chmod
),
597 SCMP_CMP_STR(0, SCMP_CMP_EQ
, param
->value
));
599 log_err(LD_BUG
,"(Sandbox) failed to add chmod syscall, received "
600 "libseccomp error %d", rc
);
610 sb_fchmodat(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
613 sandbox_cfg_t
*elem
= NULL
;
615 // for each dynamic parameter filters
616 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
617 smp_param_t
*param
= elem
->param
;
619 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
620 == SCMP_SYS(fchmodat
)) {
621 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fchmodat
),
622 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD
),
623 SCMP_CMP_STR(1, SCMP_CMP_EQ
, param
->value
));
625 log_err(LD_BUG
,"(Sandbox) failed to add fchmodat syscall, received "
626 "libseccomp error %d", rc
);
637 sb_chown32(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
640 sandbox_cfg_t
*elem
= NULL
;
642 // for each dynamic parameter filters
643 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
644 smp_param_t
*param
= elem
->param
;
646 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
647 == SCMP_SYS(chown32
)) {
648 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(chown32
),
649 SCMP_CMP_STR(0, SCMP_CMP_EQ
, param
->value
));
651 log_err(LD_BUG
,"(Sandbox) failed to add chown32 syscall, received "
652 "libseccomp error %d", rc
);
662 sb_chown(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
665 sandbox_cfg_t
*elem
= NULL
;
667 // for each dynamic parameter filters
668 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
669 smp_param_t
*param
= elem
->param
;
671 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
672 == SCMP_SYS(chown
)) {
673 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(chown
),
674 SCMP_CMP_STR(0, SCMP_CMP_EQ
, param
->value
));
676 log_err(LD_BUG
,"(Sandbox) failed to add chown syscall, received "
677 "libseccomp error %d", rc
);
685 #endif /* defined(__i386__) */
688 sb_fchownat(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
691 sandbox_cfg_t
*elem
= NULL
;
693 // for each dynamic parameter filters
694 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
695 smp_param_t
*param
= elem
->param
;
697 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
698 == SCMP_SYS(fchownat
)) {
699 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fchownat
),
700 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD
),
701 SCMP_CMP_STR(1, SCMP_CMP_EQ
, param
->value
));
703 log_err(LD_BUG
,"(Sandbox) failed to add fchownat syscall, received "
704 "libseccomp error %d", rc
);
714 * Function responsible for setting up the rename syscall for
715 * the seccomp filter sandbox.
718 sb_rename(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
721 sandbox_cfg_t
*elem
= NULL
;
723 // for each dynamic parameter filters
724 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
725 smp_param_t
*param
= elem
->param
;
727 if (param
!= NULL
&& param
->prot
== 1 &&
728 param
->syscall
== SCMP_SYS(rename
)) {
730 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rename
),
731 SCMP_CMP_STR(0, SCMP_CMP_EQ
, param
->value
),
732 SCMP_CMP_STR(1, SCMP_CMP_EQ
, param
->value2
));
734 log_err(LD_BUG
,"(Sandbox) failed to add rename syscall, received "
735 "libseccomp error %d", rc
);
745 * Function responsible for setting up the renameat syscall for
746 * the seccomp filter sandbox.
749 sb_renameat(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
752 sandbox_cfg_t
*elem
= NULL
;
754 // for each dynamic parameter filters
755 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
756 smp_param_t
*param
= elem
->param
;
758 if (param
!= NULL
&& param
->prot
== 1 &&
759 param
->syscall
== SCMP_SYS(renameat
)) {
761 rc
= seccomp_rule_add_4(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(renameat
),
762 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD
),
763 SCMP_CMP_STR(1, SCMP_CMP_EQ
, param
->value
),
764 SCMP_CMP_LOWER32_EQ(2, AT_FDCWD
),
765 SCMP_CMP_STR(3, SCMP_CMP_EQ
, param
->value2
));
767 log_err(LD_BUG
,"(Sandbox) failed to add renameat syscall, received "
768 "libseccomp error %d", rc
);
778 * Function responsible for setting up the openat syscall for
779 * the seccomp filter sandbox.
782 sb_openat(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
785 sandbox_cfg_t
*elem
= NULL
;
787 // for each dynamic parameter filters
788 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
789 smp_param_t
*param
= elem
->param
;
791 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
792 == SCMP_SYS(openat
)) {
793 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(openat
),
794 SCMP_CMP_LOWER32_EQ(0, AT_FDCWD
),
795 SCMP_CMP_STR(1, SCMP_CMP_EQ
, param
->value
),
796 SCMP_CMP(2, SCMP_CMP_EQ
, O_RDONLY
|O_NONBLOCK
|O_LARGEFILE
|O_DIRECTORY
|
799 log_err(LD_BUG
,"(Sandbox) failed to add openat syscall, received "
800 "libseccomp error %d", rc
);
810 sb_opendir(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
813 sandbox_cfg_t
*elem
= NULL
;
815 // for each dynamic parameter filters
816 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
817 smp_param_t
*param
= elem
->param
;
819 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
820 == PHONY_OPENDIR_SYSCALL
) {
821 rc
= allow_file_open(ctx
, libc_uses_openat_for_opendir(), param
->value
);
823 log_err(LD_BUG
,"(Sandbox) failed to add openat syscall, received "
824 "libseccomp error %d", rc
);
833 #ifdef ENABLE_FRAGILE_HARDENING
835 * Function responsible for setting up the ptrace syscall for
836 * the seccomp filter sandbox.
839 sb_ptrace(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
842 pid_t pid
= getpid();
845 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(ptrace
),
846 SCMP_CMP(0, SCMP_CMP_EQ
, PTRACE_ATTACH
),
847 SCMP_CMP(1, SCMP_CMP_EQ
, pid
));
851 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(ptrace
),
852 SCMP_CMP(0, SCMP_CMP_EQ
, PTRACE_GETREGS
),
853 SCMP_CMP(1, SCMP_CMP_EQ
, pid
));
862 * Function responsible for setting up the socket syscall for
863 * the seccomp filter sandbox.
866 sb_socket(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
873 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
));
878 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
879 SCMP_CMP(0, SCMP_CMP_EQ
, PF_FILE
),
880 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_STREAM
));
884 for (i
= 0; i
< 2; ++i
) {
885 const int pf
= i
? PF_INET
: PF_INET6
;
886 for (j
=0; j
< 3; ++j
) {
887 const int type
= (j
== 0) ? SOCK_STREAM
:
889 const int protocol
= (j
== 0) ? IPPROTO_TCP
:
890 (j
== 1) ? IPPROTO_IP
:
892 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
893 SCMP_CMP(0, SCMP_CMP_EQ
, pf
),
894 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, type
),
895 SCMP_CMP(2, SCMP_CMP_EQ
, protocol
));
902 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
903 SCMP_CMP(0, SCMP_CMP_EQ
, PF_INET
),
904 SCMP_CMP(1, SCMP_CMP_EQ
, SOCK_STREAM
),
905 SCMP_CMP(2, SCMP_CMP_EQ
, IPPROTO_IP
));
908 #endif /* defined(ENABLE_NSS) */
910 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
911 SCMP_CMP(0, SCMP_CMP_EQ
, PF_UNIX
),
912 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_STREAM
),
913 SCMP_CMP(2, SCMP_CMP_EQ
, 0));
917 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
918 SCMP_CMP(0, SCMP_CMP_EQ
, PF_UNIX
),
919 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_DGRAM
),
920 SCMP_CMP(2, SCMP_CMP_EQ
, 0));
924 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
925 SCMP_CMP(0, SCMP_CMP_EQ
, PF_NETLINK
),
926 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
, SOCK_RAW
),
927 SCMP_CMP(2, SCMP_CMP_EQ
, 0));
935 * Function responsible for setting up the socketpair syscall for
936 * the seccomp filter sandbox.
939 sb_socketpair(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
945 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketpair
));
950 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketpair
),
951 SCMP_CMP(0, SCMP_CMP_EQ
, PF_FILE
),
952 SCMP_CMP(1, SCMP_CMP_EQ
, SOCK_STREAM
|SOCK_CLOEXEC
));
959 #ifdef HAVE_KIST_SUPPORT
961 #include <linux/sockios.h>
964 sb_ioctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
969 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(ioctl
),
970 SCMP_CMP(1, SCMP_CMP_EQ
, SIOCOUTQNSD
));
976 #endif /* defined(HAVE_KIST_SUPPORT) */
979 * Function responsible for setting up the setsockopt syscall for
980 * the seccomp filter sandbox.
983 sb_setsockopt(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
989 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
));
994 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
995 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
996 SCMP_CMP(2, SCMP_CMP_EQ
, SO_REUSEADDR
));
1000 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
1001 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1002 SCMP_CMP(2, SCMP_CMP_EQ
, SO_SNDBUF
));
1006 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
1007 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1008 SCMP_CMP(2, SCMP_CMP_EQ
, SO_RCVBUF
));
1013 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
1014 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1015 SCMP_CMP(2, SCMP_CMP_EQ
, SO_SNDBUFFORCE
));
1018 #endif /* defined(HAVE_SYSTEMD) */
1020 #ifdef IP_TRANSPARENT
1021 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
1022 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_IP
),
1023 SCMP_CMP(2, SCMP_CMP_EQ
, IP_TRANSPARENT
));
1026 #endif /* defined(IP_TRANSPARENT) */
1029 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
1030 SCMP_CMP(1, SCMP_CMP_EQ
, IPPROTO_IPV6
),
1031 SCMP_CMP(2, SCMP_CMP_EQ
, IPV6_V6ONLY
));
1034 #endif /* defined(IPV6_V6ONLY) */
1040 * Function responsible for setting up the getsockopt syscall for
1041 * the seccomp filter sandbox.
1044 sb_getsockopt(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1050 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
));
1055 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1056 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1057 SCMP_CMP(2, SCMP_CMP_EQ
, SO_ERROR
));
1061 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1062 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1063 SCMP_CMP(2, SCMP_CMP_EQ
, SO_ACCEPTCONN
));
1068 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1069 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
1070 SCMP_CMP(2, SCMP_CMP_EQ
, SO_SNDBUF
));
1073 #endif /* defined(HAVE_SYSTEMD) */
1075 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
1076 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1077 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_IP
),
1078 SCMP_CMP(2, SCMP_CMP_EQ
, SO_ORIGINAL_DST
));
1081 #endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
1083 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
1084 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1085 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_IPV6
),
1086 SCMP_CMP(2, SCMP_CMP_EQ
, IP6T_SO_ORIGINAL_DST
));
1089 #endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
1091 #ifdef HAVE_KIST_SUPPORT
1092 #include <netinet/tcp.h>
1093 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
1094 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_TCP
),
1095 SCMP_CMP(2, SCMP_CMP_EQ
, TCP_INFO
));
1098 #endif /* defined(HAVE_KIST_SUPPORT) */
1105 * Function responsible for setting up the fcntl64 syscall for
1106 * the seccomp filter sandbox.
1109 sb_fcntl64(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1114 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
1115 SCMP_CMP(1, SCMP_CMP_EQ
, F_GETFL
));
1119 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
1120 SCMP_CMP(1, SCMP_CMP_EQ
, F_SETFL
),
1121 SCMP_CMP(2, SCMP_CMP_EQ
, O_RDWR
|O_NONBLOCK
));
1125 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
1126 SCMP_CMP(1, SCMP_CMP_EQ
, F_GETFD
));
1130 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
1131 SCMP_CMP(1, SCMP_CMP_EQ
, F_SETFD
),
1132 SCMP_CMP(2, SCMP_CMP_EQ
, FD_CLOEXEC
));
1138 #endif /* defined(__NR_fcntl64) */
1141 * Function responsible for setting up the epoll_ctl syscall for
1142 * the seccomp filter sandbox.
1144 * Note: basically allows everything but will keep for now..
1147 sb_epoll_ctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1152 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
1153 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_ADD
));
1157 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
1158 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_MOD
));
1162 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
1163 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_DEL
));
1171 * Function responsible for setting up the prctl syscall for
1172 * the seccomp filter sandbox.
1174 * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
1175 * to be allowlisted in this function.
1178 sb_prctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1183 #ifdef ENABLE_FRAGILE_HARDENING
1184 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(prctl
),
1185 SCMP_CMP(0, SCMP_CMP_EQ
, PR_GET_DUMPABLE
));
1189 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(prctl
),
1190 SCMP_CMP(0, SCMP_CMP_EQ
, PR_SET_PTRACER
));
1195 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(prctl
),
1196 SCMP_CMP(0, SCMP_CMP_EQ
, PR_SET_DUMPABLE
));
1204 * Function responsible for setting up the mprotect syscall for
1205 * the seccomp filter sandbox.
1207 * NOTE: does not NEED to be here.. currently only occurs before filter; will
1208 * keep just in case for the future.
1211 sb_mprotect(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1216 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1217 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
));
1221 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1222 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_NONE
));
1230 * Function responsible for setting up the rt_sigprocmask syscall for
1231 * the seccomp filter sandbox.
1234 sb_rt_sigprocmask(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1239 #ifdef ENABLE_FRAGILE_HARDENING
1240 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigprocmask
),
1241 SCMP_CMP(0, SCMP_CMP_EQ
, SIG_BLOCK
));
1246 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigprocmask
),
1247 SCMP_CMP(0, SCMP_CMP_EQ
, SIG_UNBLOCK
));
1251 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigprocmask
),
1252 SCMP_CMP(0, SCMP_CMP_EQ
, SIG_SETMASK
));
1260 * Function responsible for setting up the flock syscall for
1261 * the seccomp filter sandbox.
1263 * NOTE: does not need to be here, occurs before filter is applied.
1266 sb_flock(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1271 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(flock
),
1272 SCMP_CMP(1, SCMP_CMP_EQ
, LOCK_EX
|LOCK_NB
));
1276 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(flock
),
1277 SCMP_CMP(1, SCMP_CMP_EQ
, LOCK_UN
));
1285 * Function responsible for setting up the futex syscall for
1286 * the seccomp filter sandbox.
1289 sb_futex(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1295 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
1296 SCMP_CMP(1, SCMP_CMP_EQ
,
1297 FUTEX_WAIT_BITSET_PRIVATE
|FUTEX_CLOCK_REALTIME
));
1301 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
1302 SCMP_CMP(1, SCMP_CMP_EQ
, FUTEX_WAKE_PRIVATE
));
1306 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
1307 SCMP_CMP(1, SCMP_CMP_EQ
, FUTEX_WAIT_PRIVATE
));
1315 * Function responsible for setting up the mremap syscall for
1316 * the seccomp filter sandbox.
1318 * NOTE: so far only occurs before filter is applied.
1321 sb_mremap(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1326 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mremap
),
1327 SCMP_CMP(3, SCMP_CMP_EQ
, MREMAP_MAYMOVE
));
1336 * Function responsible for setting up the stat64 syscall for
1337 * the seccomp filter sandbox.
1340 sb_stat64(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1343 sandbox_cfg_t
*elem
= NULL
;
1345 // for each dynamic parameter filters
1346 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
1347 smp_param_t
*param
= elem
->param
;
1349 if (param
!= NULL
&& param
->prot
== 1 && (param
->syscall
== SCMP_SYS(open
)
1350 || param
->syscall
== SCMP_SYS(stat64
))) {
1351 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(stat64
),
1352 SCMP_CMP_STR(0, SCMP_CMP_EQ
, param
->value
));
1354 log_err(LD_BUG
,"(Sandbox) failed to add stat64 syscall, received "
1355 "libseccomp error %d", rc
);
1363 #endif /* defined(__NR_stat64) */
1366 sb_kill(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
1370 /* Allow killing anything with signal 0 -- it isn't really a kill. */
1371 return seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(kill
),
1372 SCMP_CMP(1, SCMP_CMP_EQ
, 0));
1375 #endif /* defined(__NR_kill) */
1379 * Array of function pointers responsible for filtering different syscalls at
1380 * a parameter level.
1382 static sandbox_filter_func_t filter_func
[] = {
1403 #ifdef ENABLE_FRAGILE_HARDENING
1425 #ifdef HAVE_KIST_SUPPORT
1432 * Return the interned (and hopefully sandbox-permitted) string equal
1435 * Return NULL if `str` is NULL, or `str` is not an interned string.
1438 sandbox_intern_string(const char *str
)
1440 const char *interned
= sandbox_get_interned_string(str
);
1442 if (sandbox_active
&& str
!= NULL
&& interned
== NULL
) {
1443 log_warn(LD_BUG
, "No interned sandbox parameter found for %s", str
);
1446 return interned
? interned
: str
;
1450 * Return true if the sandbox is running and we are missing an interned string
1454 sandbox_interned_string_is_missing(const char *str
)
1456 return sandbox_active
&& sandbox_get_interned_string(str
) == NULL
;
1460 * Try to find and return the interned string equal to @a str.
1462 * If there is no such string, return NULL.
1465 sandbox_get_interned_string(const char *str
)
1467 sandbox_cfg_t
*elem
;
1472 for (elem
= filter_dynamic
; elem
!= NULL
; elem
= elem
->next
) {
1473 smp_param_t
*param
= elem
->param
;
1476 if (!strcmp(str
, (char*)(param
->value
))) {
1477 return (char*)param
->value
;
1479 if (param
->value2
&& !strcmp(str
, (char*)param
->value2
)) {
1480 return (char*)param
->value2
;
1490 prot_strings_helper(strmap_t
*locations
,
1491 char **pr_mem_next_p
,
1492 size_t *pr_mem_left_p
,
1502 param_val
= (char*) *value_p
;
1503 param_size
= strlen(param_val
) + 1;
1504 location
= strmap_get(locations
, param_val
);
1507 // We already interned this string.
1508 tor_free(param_val
);
1509 *value_p
= location
;
1511 } else if (*pr_mem_left_p
>= param_size
) {
1512 // copy to protected
1513 location
= *pr_mem_next_p
;
1514 memcpy(location
, param_val
, param_size
);
1516 // re-point el parameter to protected
1517 tor_free(param_val
);
1518 *value_p
= location
;
1520 strmap_set(locations
, location
, location
); /* good real estate advice */
1522 // move next available protected memory
1523 *pr_mem_next_p
+= param_size
;
1524 *pr_mem_left_p
-= param_size
;
1527 log_err(LD_BUG
,"(Sandbox) insufficient protected memory!");
1533 * Protects all the strings in the sandbox's parameter list configuration. It
1534 * works by calculating the total amount of memory required by the parameter
1535 * list, allocating the memory using mmap, and protecting it from writes with
1539 prot_strings(scmp_filter_ctx ctx
, sandbox_cfg_t
* cfg
)
1542 size_t pr_mem_size
= 0, pr_mem_left
= 0;
1543 char *pr_mem_next
= NULL
, *pr_mem_base
;
1544 sandbox_cfg_t
*el
= NULL
;
1545 strmap_t
*locations
= NULL
;
1547 // get total number of bytes required to mmap. (Overestimate.)
1548 for (el
= cfg
; el
!= NULL
; el
= el
->next
) {
1549 pr_mem_size
+= strlen((char*) el
->param
->value
) + 1;
1550 if (el
->param
->value2
)
1551 pr_mem_size
+= strlen((char*) el
->param
->value2
) + 1;
1554 // allocate protected memory with MALLOC_MP_LIM canary
1555 pr_mem_base
= (char*) mmap(NULL
, MALLOC_MP_LIM
+ pr_mem_size
,
1556 PROT_READ
| PROT_WRITE
, MAP_PRIVATE
| MAP_ANON
, -1, 0);
1557 if (pr_mem_base
== MAP_FAILED
) {
1558 log_err(LD_BUG
,"(Sandbox) failed allocate protected memory! mmap: %s",
1564 pr_mem_next
= pr_mem_base
+ MALLOC_MP_LIM
;
1565 pr_mem_left
= pr_mem_size
;
1567 locations
= strmap_new();
1569 // change el value pointer to protected
1570 for (el
= cfg
; el
!= NULL
; el
= el
->next
) {
1571 if (prot_strings_helper(locations
, &pr_mem_next
, &pr_mem_left
,
1572 &el
->param
->value
) < 0) {
1576 if (prot_strings_helper(locations
, &pr_mem_next
, &pr_mem_left
,
1577 &el
->param
->value2
) < 0) {
1581 el
->param
->prot
= 1;
1584 // protecting from writes
1585 if (mprotect(pr_mem_base
, MALLOC_MP_LIM
+ pr_mem_size
, PROT_READ
)) {
1586 log_err(LD_BUG
,"(Sandbox) failed to protect memory! mprotect: %s",
1593 * Setting sandbox restrictions so the string memory cannot be tampered with
1595 // no mremap of the protected base address
1596 ret
= seccomp_rule_add_1(ctx
, SCMP_ACT_KILL
, SCMP_SYS(mremap
),
1597 SCMP_CMP(0, SCMP_CMP_EQ
, (intptr_t) pr_mem_base
));
1599 log_err(LD_BUG
,"(Sandbox) mremap protected memory filter fail!");
1603 // no munmap of the protected base address
1604 ret
= seccomp_rule_add_1(ctx
, SCMP_ACT_KILL
, SCMP_SYS(munmap
),
1605 SCMP_CMP(0, SCMP_CMP_EQ
, (intptr_t) pr_mem_base
));
1607 log_err(LD_BUG
,"(Sandbox) munmap protected memory filter fail!");
1612 * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
1613 * never over the memory region used by the protected strings.
1615 * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
1616 * had to be removed due to limitation of libseccomp regarding intervals.
1618 * There is a restriction on how much you can mprotect with R|W up to the
1619 * size of the canary.
1621 ret
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1622 SCMP_CMP(0, SCMP_CMP_LT
, (intptr_t) pr_mem_base
),
1623 SCMP_CMP(1, SCMP_CMP_LE
, MALLOC_MP_LIM
),
1624 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
));
1626 log_err(LD_BUG
,"(Sandbox) mprotect protected memory filter fail (LT)!");
1630 ret
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1631 SCMP_CMP(0, SCMP_CMP_GT
, (intptr_t) pr_mem_base
+ pr_mem_size
+
1633 SCMP_CMP(1, SCMP_CMP_LE
, MALLOC_MP_LIM
),
1634 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
));
1636 log_err(LD_BUG
,"(Sandbox) mprotect protected memory filter fail (GT)!");
1641 strmap_free(locations
, NULL
);
1646 * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
1647 * its values according the parameter list. All elements are initialised
1648 * with the 'prot' field set to false, as the pointer is not protected at this
1651 static sandbox_cfg_t
*
1652 new_element2(int syscall
, char *value
, char *value2
)
1654 smp_param_t
*param
= NULL
;
1656 sandbox_cfg_t
*elem
= tor_malloc_zero(sizeof(sandbox_cfg_t
));
1657 param
= elem
->param
= tor_malloc_zero(sizeof(smp_param_t
));
1659 param
->syscall
= syscall
;
1660 param
->value
= value
;
1661 param
->value2
= value2
;
1667 static sandbox_cfg_t
*
1668 new_element(int syscall
, char *value
)
1670 return new_element2(syscall
, value
, NULL
);
1674 #define SCMP_chown SCMP_SYS(chown32)
1675 #elif defined(__aarch64__) && defined(__LP64__)
1676 #define SCMP_chown SCMP_SYS(fchownat)
1678 #define SCMP_chown SCMP_SYS(chown)
1681 #if defined(__aarch64__) && defined(__LP64__)
1682 #define SCMP_chmod SCMP_SYS(fchmodat)
1684 #define SCMP_chmod SCMP_SYS(chmod)
1687 #if defined(__aarch64__) && defined(__LP64__)
1688 #define SCMP_rename SCMP_SYS(renameat)
1690 #define SCMP_rename SCMP_SYS(rename)
1694 #define SCMP_stat SCMP_SYS(stat64)
1696 #define SCMP_stat SCMP_SYS(stat)
1700 sandbox_cfg_allow_stat_filename(sandbox_cfg_t
**cfg
, char *file
)
1702 sandbox_cfg_t
*elem
= NULL
;
1704 elem
= new_element(SCMP_stat
, file
);
1713 sandbox_cfg_allow_open_filename(sandbox_cfg_t
**cfg
, char *file
)
1715 sandbox_cfg_t
*elem
= NULL
;
1717 elem
= new_element(SCMP_SYS(open
), file
);
1726 sandbox_cfg_allow_chmod_filename(sandbox_cfg_t
**cfg
, char *file
)
1728 sandbox_cfg_t
*elem
= NULL
;
1730 elem
= new_element(SCMP_chmod
, file
);
1739 sandbox_cfg_allow_chown_filename(sandbox_cfg_t
**cfg
, char *file
)
1741 sandbox_cfg_t
*elem
= NULL
;
1743 elem
= new_element(SCMP_chown
, file
);
1752 sandbox_cfg_allow_rename(sandbox_cfg_t
**cfg
, char *file1
, char *file2
)
1754 sandbox_cfg_t
*elem
= NULL
;
1756 elem
= new_element2(SCMP_rename
, file1
, file2
);
1765 sandbox_cfg_allow_openat_filename(sandbox_cfg_t
**cfg
, char *file
)
1767 sandbox_cfg_t
*elem
= NULL
;
1769 elem
= new_element(SCMP_SYS(openat
), file
);
1778 sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t
**cfg
, char *dir
)
1780 sandbox_cfg_t
*elem
= NULL
;
1782 elem
= new_element(PHONY_OPENDIR_SYSCALL
, dir
);
1791 * Function responsible for going through the parameter syscall filters and
1792 * call each function pointer in the list.
1795 add_param_filter(scmp_filter_ctx ctx
, sandbox_cfg_t
* cfg
)
1801 for (i
= 0; i
< ARRAY_LENGTH(filter_func
); i
++) {
1802 rc
= filter_func
[i
](ctx
, cfg
);
1804 log_err(LD_BUG
,"(Sandbox) failed to add syscall %d, received libseccomp "
1814 * Function responsible of loading the libseccomp syscall filters which do not
1815 * have parameter filtering.
1818 add_noparam_filter(scmp_filter_ctx ctx
)
1823 // add general filters
1824 for (i
= 0; i
< ARRAY_LENGTH(filter_nopar_gen
); i
++) {
1825 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, filter_nopar_gen
[i
]);
1827 log_err(LD_BUG
,"(Sandbox) failed to add syscall index %d (NR=%d), "
1828 "received libseccomp error %d", i
, filter_nopar_gen
[i
], rc
);
1833 if (is_libc_at_least(2, 33)) {
1834 #ifdef __NR_newfstatat
1835 // Libc 2.33 uses this syscall to implement both fstat() and stat().
1837 // The trouble is that to implement fstat(fd, &st), it calls:
1838 // newfstatat(fs, "", &st, AT_EMPTY_PATH)
1839 // We can't detect this usage in particular, because "" is a pointer
1840 // we don't control. And we can't just look for AT_EMPTY_PATH, since
1841 // AT_EMPTY_PATH only has effect when the path string is empty.
1843 // So our only solution seems to be allowing all fstatat calls, which
1844 // means that an attacker can stat() anything on the filesystem. That's
1845 // not a great solution, but I can't find a better one.
1846 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(newfstatat
));
1848 log_err(LD_BUG
,"(Sandbox) failed to add newfstatat() syscall; "
1849 "received libseccomp error %d", rc
);
1859 * Function responsible for setting up and enabling a global syscall filter.
1860 * The function is a prototype developed for stage 1 of sandboxing Tor.
1861 * Returns 0 on success.
1864 install_syscall_filter(sandbox_cfg_t
* cfg
)
1867 scmp_filter_ctx ctx
;
1869 ctx
= seccomp_init(SCMP_ACT_ERRNO(EPERM
));
1871 log_err(LD_BUG
,"(Sandbox) failed to initialise libseccomp context");
1876 // protecting sandbox parameter strings
1877 if ((rc
= prot_strings(ctx
, cfg
))) {
1881 // add parameter filters
1882 if ((rc
= add_param_filter(ctx
, cfg
))) {
1883 log_err(LD_BUG
, "(Sandbox) failed to add param filters!");
1887 // adding filters with no parameters
1888 if ((rc
= add_noparam_filter(ctx
))) {
1889 log_err(LD_BUG
, "(Sandbox) failed to add param filters!");
1893 // loading the seccomp2 filter
1894 if ((rc
= seccomp_load(ctx
))) {
1895 log_err(LD_BUG
, "(Sandbox) failed to load: %d (%s)! "
1896 "Are you sure that your kernel has seccomp2 support? The "
1897 "sandbox won't work without it.", rc
,
1902 // marking the sandbox as active
1906 seccomp_release(ctx
);
1907 return (rc
< 0 ? -rc
: rc
);
1910 #ifdef SYSCALL_NAME_DEBUGGING
1911 #include "lib/sandbox/linux_syscalls.inc"
1913 /** Return a string containing the name of a given syscall (if we know it) */
1915 get_syscall_name(int syscall_num
)
1918 for (i
= 0; SYSCALLS_BY_NUMBER
[i
].syscall_name
; ++i
) {
1919 if (SYSCALLS_BY_NUMBER
[i
].syscall_num
== syscall_num
)
1920 return SYSCALLS_BY_NUMBER
[i
].syscall_name
;
1924 static char syscall_name_buf
[64];
1925 format_dec_number_sigsafe(syscall_num
,
1926 syscall_name_buf
, sizeof(syscall_name_buf
));
1927 return syscall_name_buf
;
1931 /** Return the syscall number from a ucontext_t that we got in a signal
1932 * handler (if we know how to do that). */
1934 get_syscall_from_ucontext(const ucontext_t
*ctx
)
1936 return (int) ctx
->uc_mcontext
.M_SYSCALL
;
1938 #else /* !defined(SYSCALL_NAME_DEBUGGING) */
1940 get_syscall_name(int syscall_num
)
1946 get_syscall_from_ucontext(const ucontext_t
*ctx
)
1951 #endif /* defined(SYSCALL_NAME_DEBUGGING) */
1953 #ifdef USE_BACKTRACE
1954 #define MAX_DEPTH 256
1955 static void *syscall_cb_buf
[MAX_DEPTH
];
1959 * Function called when a SIGSYS is caught by the application. It notifies the
1960 * user that an error has occurred and either terminates or allows the
1961 * application to continue execution, based on the DEBUGGING_CLOSE symbol.
1964 sigsys_debugging(int nr
, siginfo_t
*info
, void *void_context
)
1966 ucontext_t
*ctx
= (ucontext_t
*) (void_context
);
1967 const char *syscall_name
;
1968 #ifdef USE_BACKTRACE
1971 const int *fds
= NULL
;
1976 if (info
->si_code
!= SYS_SECCOMP
)
1982 int syscall
= get_syscall_from_ucontext(ctx
);
1984 #ifdef USE_BACKTRACE
1985 depth
= backtrace(syscall_cb_buf
, MAX_DEPTH
);
1986 /* Clean up the top stack frame so we get the real function
1987 * name for the most recently failing function. */
1988 clean_backtrace(syscall_cb_buf
, depth
, ctx
);
1989 #endif /* defined(USE_BACKTRACE) */
1991 syscall_name
= get_syscall_name(syscall
);
1993 tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1998 #ifdef USE_BACKTRACE
1999 n_fds
= tor_log_get_sigsafe_err_fds(&fds
);
2000 for (i
=0; i
< n_fds
; ++i
)
2001 backtrace_symbols_fd(syscall_cb_buf
, (int)depth
, fds
[i
]);
2004 #if defined(DEBUGGING_CLOSE)
2005 _exit(1); // exit ok: programming error has led to sandbox failure.
2006 #endif // DEBUGGING_CLOSE
2010 * Function that adds a handler for SIGSYS, which is the signal thrown
2011 * when the application is issuing a syscall which is not allowed. The
2012 * main purpose of this function is to help with debugging by identifying
2013 * filtered syscalls.
2016 install_sigsys_debugging(void)
2018 struct sigaction act
;
2021 memset(&act
, 0, sizeof(act
));
2023 sigaddset(&mask
, SIGSYS
);
2025 act
.sa_sigaction
= &sigsys_debugging
;
2026 act
.sa_flags
= SA_SIGINFO
;
2027 if (sigaction(SIGSYS
, &act
, NULL
) < 0) {
2028 log_err(LD_BUG
,"(Sandbox) Failed to register SIGSYS signal handler");
2032 if (sigprocmask(SIG_UNBLOCK
, &mask
, NULL
)) {
2033 log_err(LD_BUG
,"(Sandbox) Failed call to sigprocmask()");
2041 * Function responsible of registering the sandbox_cfg_t list of parameter
2042 * syscall filters to the existing parameter list. This is used for incipient
2043 * multiple-sandbox support.
2046 register_cfg(sandbox_cfg_t
* cfg
)
2048 sandbox_cfg_t
*elem
= NULL
;
2050 if (filter_dynamic
== NULL
) {
2051 filter_dynamic
= cfg
;
2055 for (elem
= filter_dynamic
; elem
->next
!= NULL
; elem
= elem
->next
)
2063 #endif /* defined(USE_LIBSECCOMP) */
2065 #ifdef USE_LIBSECCOMP
2067 * Initialises the syscall sandbox filter for any linux architecture, taking
2068 * into account various available features for different linux flavours.
2071 initialise_libseccomp_sandbox(sandbox_cfg_t
* cfg
)
2073 /* Prevent glibc from trying to open /dev/tty on fatal error */
2074 setenv("LIBC_FATAL_STDERR_", "1", 1);
2076 if (install_sigsys_debugging())
2079 if (install_syscall_filter(cfg
))
2082 if (register_cfg(cfg
))
2089 sandbox_is_active(void)
2091 return sandbox_active
!= 0;
2093 #endif /* defined(USE_LIBSECCOMP) */
2096 sandbox_cfg_new(void)
2102 sandbox_init(sandbox_cfg_t
*cfg
)
2104 #if defined(USE_LIBSECCOMP)
2105 return initialise_libseccomp_sandbox(cfg
);
2107 #elif defined(__linux__)
2109 log_warn(LD_GENERAL
,
2110 "This version of Tor was built without support for sandboxing. To "
2111 "build with support for sandboxing on Linux, you must have "
2112 "libseccomp and its necessary header files (e.g. seccomp.h).");
2117 log_warn(LD_GENERAL
,
2118 "Currently, sandboxing is only implemented on Linux. The feature "
2119 "is disabled on your platform.");
2121 #endif /* defined(USE_LIBSECCOMP) || ... */
2124 #ifndef USE_LIBSECCOMP
2126 sandbox_cfg_allow_open_filename(sandbox_cfg_t
**cfg
, char *file
)
2128 (void)cfg
; (void)file
;
2133 sandbox_cfg_allow_openat_filename(sandbox_cfg_t
**cfg
, char *file
)
2135 (void)cfg
; (void)file
;
2140 sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t
**cfg
, char *dir
)
2142 (void)cfg
; (void)dir
;
2147 sandbox_cfg_allow_stat_filename(sandbox_cfg_t
**cfg
, char *file
)
2149 (void)cfg
; (void)file
;
2154 sandbox_cfg_allow_chown_filename(sandbox_cfg_t
**cfg
, char *file
)
2156 (void)cfg
; (void)file
;
2161 sandbox_cfg_allow_chmod_filename(sandbox_cfg_t
**cfg
, char *file
)
2163 (void)cfg
; (void)file
;
2168 sandbox_cfg_allow_rename(sandbox_cfg_t
**cfg
, char *file1
, char *file2
)
2170 (void)cfg
; (void)file1
; (void)file2
;
2175 sandbox_is_active(void)
2180 #endif /* !defined(USE_LIBSECCOMP) */