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-2013, 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
22 /** Malloc mprotect limit in bytes. */
23 #define MALLOC_MP_LIM 1048576
30 #include "container.h"
34 #include "tor_queue.h"
36 #define DEBUGGING_CLOSE
38 #if defined(USE_LIBSECCOMP)
43 #include <sys/syscall.h>
44 #include <sys/types.h>
46 #include <sys/epoll.h>
47 #include <sys/prctl.h>
48 #include <linux/futex.h>
49 #include <bits/signum.h>
59 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
60 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
62 #define EXPOSE_CLEAN_BACKTRACE
63 #include "backtrace.h"
70 /**Determines if at least one sandbox is active.*/
71 static int sandbox_active
= 0;
72 /** Holds the parameter list configuration for the sandbox.*/
73 static sandbox_cfg_t
*filter_dynamic
= NULL
;
74 /** Holds a list of pre-recorded results from getaddrinfo().*/
75 static sb_addr_info_t
*sb_addr_info
= NULL
;
78 #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
79 #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
80 /* We use a wrapper here because these masked comparisons seem to be pretty
81 * verbose. Also, it's important to cast to scmp_datum_t before negating the
82 * mask, since otherwise the negation might get applied to a 32 bit value, and
83 * the high bits of the value might get masked out improperly. */
84 #define SCMP_CMP_MASKED(a,b,c) \
85 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
87 /** Variable used for storing all syscall numbers that will be allowed with the
88 * stage 1 general Tor sandbox.
90 static int filter_nopar_gen
[] = {
93 SCMP_SYS(clock_gettime
),
96 SCMP_SYS(epoll_create
),
103 SCMP_SYS(getdents64
),
105 #ifdef __NR_getegid32
109 #ifdef __NR_geteuid32
117 SCMP_SYS(gettimeofday
),
132 SCMP_SYS(rt_sigreturn
),
133 SCMP_SYS(sched_getaffinity
),
134 SCMP_SYS(set_robust_list
),
135 #ifdef __NR_sigreturn
142 SCMP_SYS(exit_group
),
147 // getaddrinfo uses this..
152 * These socket syscalls are not required on x86_64 and not supported with
153 * some libseccomp versions (eg: 1.0.1)
163 SCMP_SYS(getsockname
),
170 /* These macros help avoid the error where the number of filters we add on a
171 * single rule don't match the arg_cnt param. */
172 #define seccomp_rule_add_0(ctx,act,call) \
173 seccomp_rule_add((ctx),(act),(call),0)
174 #define seccomp_rule_add_1(ctx,act,call,f1) \
175 seccomp_rule_add((ctx),(act),(call),1,(f1))
176 #define seccomp_rule_add_2(ctx,act,call,f1,f2) \
177 seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
178 #define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
179 seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
180 #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
181 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
184 * Function responsible for setting up the rt_sigaction syscall for
185 * the seccomp filter sandbox.
188 sb_rt_sigaction(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
192 int param
[] = { SIGINT
, SIGTERM
, SIGPIPE
, SIGUSR1
, SIGUSR2
, SIGHUP
, SIGCHLD
,
199 for (i
= 0; i
< ARRAY_LENGTH(param
); i
++) {
200 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigaction
),
201 SCMP_CMP(0, SCMP_CMP_EQ
, param
[i
]));
211 * Function responsible for setting up the execve syscall for
212 * the seccomp filter sandbox.
215 sb_execve(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
218 sandbox_cfg_t
*elem
= NULL
;
220 // for each dynamic parameter filters
221 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
222 smp_param_t
*param
= elem
->param
;
224 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
225 == SCMP_SYS(execve
)) {
226 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(execve
),
227 SCMP_CMP(0, SCMP_CMP_EQ
, param
->value
));
229 log_err(LD_BUG
,"(Sandbox) failed to add execve syscall, received "
230 "libseccomp error %d", rc
);
241 * Function responsible for setting up the time syscall for
242 * the seccomp filter sandbox.
245 sb_time(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
248 return seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(time
),
249 SCMP_CMP(0, SCMP_CMP_EQ
, 0));
253 * Function responsible for setting up the accept4 syscall for
254 * the seccomp filter sandbox.
257 sb_accept4(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
263 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketcall
),
264 SCMP_CMP(0, SCMP_CMP_EQ
, 18));
270 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(accept4
),
271 SCMP_CMP_MASKED(3, SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0));
281 * Function responsible for setting up the mmap2 syscall for
282 * the seccomp filter sandbox.
285 sb_mmap2(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
290 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
291 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
),
292 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
));
297 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
298 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_NONE
),
299 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_ANONYMOUS
|MAP_NORESERVE
));
304 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
305 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
306 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_ANONYMOUS
));
311 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
312 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
313 SCMP_CMP(3, SCMP_CMP_EQ
,MAP_PRIVATE
|MAP_ANONYMOUS
|MAP_STACK
));
318 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
319 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
320 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_FIXED
|MAP_DENYWRITE
));
325 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
326 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
),
327 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_FIXED
|MAP_ANONYMOUS
));
332 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap2
),
333 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_EXEC
),
334 SCMP_CMP(3, SCMP_CMP_EQ
, MAP_PRIVATE
|MAP_DENYWRITE
));
344 * Function responsible for setting up the open syscall for
345 * the seccomp filter sandbox.
348 sb_open(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
351 sandbox_cfg_t
*elem
= NULL
;
353 // for each dynamic parameter filters
354 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
355 smp_param_t
*param
= elem
->param
;
357 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
359 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(open
),
360 SCMP_CMP(0, SCMP_CMP_EQ
, param
->value
));
362 log_err(LD_BUG
,"(Sandbox) failed to add open syscall, received "
363 "libseccomp error %d", rc
);
369 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ERRNO(EACCES
), SCMP_SYS(open
),
370 SCMP_CMP_MASKED(1, O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
, O_RDONLY
));
372 log_err(LD_BUG
,"(Sandbox) failed to add open syscall, received libseccomp "
381 sb__sysctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
387 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ERRNO(EPERM
), SCMP_SYS(_sysctl
));
389 log_err(LD_BUG
,"(Sandbox) failed to add _sysctl syscall, "
390 "received libseccomp error %d", rc
);
398 * Function responsible for setting up the rename syscall for
399 * the seccomp filter sandbox.
402 sb_rename(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
405 sandbox_cfg_t
*elem
= NULL
;
407 // for each dynamic parameter filters
408 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
409 smp_param_t
*param
= elem
->param
;
411 if (param
!= NULL
&& param
->prot
== 1 &&
412 param
->syscall
== SCMP_SYS(rename
)) {
414 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rename
),
415 SCMP_CMP(0, SCMP_CMP_EQ
, param
->value
),
416 SCMP_CMP(1, SCMP_CMP_EQ
, param
->value2
));
418 log_err(LD_BUG
,"(Sandbox) failed to add rename syscall, received "
419 "libseccomp error %d", rc
);
429 * Function responsible for setting up the openat syscall for
430 * the seccomp filter sandbox.
433 sb_openat(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
436 sandbox_cfg_t
*elem
= NULL
;
438 // for each dynamic parameter filters
439 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
440 smp_param_t
*param
= elem
->param
;
442 if (param
!= NULL
&& param
->prot
== 1 && param
->syscall
443 == SCMP_SYS(openat
)) {
444 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(openat
),
445 SCMP_CMP(0, SCMP_CMP_EQ
, AT_FDCWD
),
446 SCMP_CMP(1, SCMP_CMP_EQ
, param
->value
),
447 SCMP_CMP(2, SCMP_CMP_EQ
, O_RDONLY
|O_NONBLOCK
|O_LARGEFILE
|O_DIRECTORY
|
450 log_err(LD_BUG
,"(Sandbox) failed to add openat syscall, received "
451 "libseccomp error %d", rc
);
461 * Function responsible for setting up the socket syscall for
462 * the seccomp filter sandbox.
465 sb_socket(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
472 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
));
477 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
478 SCMP_CMP(0, SCMP_CMP_EQ
, PF_FILE
),
479 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_STREAM
));
483 for (i
= 0; i
< 2; ++i
) {
484 const int pf
= i
? PF_INET
: PF_INET6
;
486 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
487 SCMP_CMP(0, SCMP_CMP_EQ
, pf
),
488 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_STREAM
),
489 SCMP_CMP(2, SCMP_CMP_EQ
, IPPROTO_TCP
));
493 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
494 SCMP_CMP(0, SCMP_CMP_EQ
, pf
),
495 SCMP_CMP_MASKED(1, SOCK_CLOEXEC
|SOCK_NONBLOCK
, SOCK_DGRAM
),
496 SCMP_CMP(2, SCMP_CMP_EQ
, IPPROTO_IP
));
501 rc
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
),
502 SCMP_CMP(0, SCMP_CMP_EQ
, PF_NETLINK
),
503 SCMP_CMP(1, SCMP_CMP_EQ
, SOCK_RAW
),
504 SCMP_CMP(2, SCMP_CMP_EQ
, 0));
512 * Function responsible for setting up the socketpair syscall for
513 * the seccomp filter sandbox.
516 sb_socketpair(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
522 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketpair
));
527 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socketpair
),
528 SCMP_CMP(0, SCMP_CMP_EQ
, PF_FILE
),
529 SCMP_CMP(1, SCMP_CMP_EQ
, SOCK_STREAM
|SOCK_CLOEXEC
));
537 * Function responsible for setting up the setsockopt syscall for
538 * the seccomp filter sandbox.
541 sb_setsockopt(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
547 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
));
552 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
553 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
554 SCMP_CMP(2, SCMP_CMP_EQ
, SO_REUSEADDR
));
558 #ifdef IP_TRANSPARENT
559 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
),
560 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_IP
),
561 SCMP_CMP(2, SCMP_CMP_EQ
, IP_TRANSPARENT
));
570 * Function responsible for setting up the getsockopt syscall for
571 * the seccomp filter sandbox.
574 sb_getsockopt(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
580 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
));
585 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockopt
),
586 SCMP_CMP(1, SCMP_CMP_EQ
, SOL_SOCKET
),
587 SCMP_CMP(2, SCMP_CMP_EQ
, SO_ERROR
));
596 * Function responsible for setting up the fcntl64 syscall for
597 * the seccomp filter sandbox.
600 sb_fcntl64(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
605 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
606 SCMP_CMP(1, SCMP_CMP_EQ
, F_GETFL
));
610 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
611 SCMP_CMP(1, SCMP_CMP_EQ
, F_SETFL
),
612 SCMP_CMP(2, SCMP_CMP_EQ
, O_RDWR
|O_NONBLOCK
));
616 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
617 SCMP_CMP(1, SCMP_CMP_EQ
, F_GETFD
));
621 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl64
),
622 SCMP_CMP(1, SCMP_CMP_EQ
, F_SETFD
),
623 SCMP_CMP(2, SCMP_CMP_EQ
, FD_CLOEXEC
));
632 * Function responsible for setting up the epoll_ctl syscall for
633 * the seccomp filter sandbox.
635 * Note: basically allows everything but will keep for now..
638 sb_epoll_ctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
643 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
644 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_ADD
));
648 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
649 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_MOD
));
653 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(epoll_ctl
),
654 SCMP_CMP(1, SCMP_CMP_EQ
, EPOLL_CTL_DEL
));
662 * Function responsible for setting up the fcntl64 syscall for
663 * the seccomp filter sandbox.
665 * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
666 * to be whitelisted in this function.
669 sb_prctl(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
674 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(prctl
),
675 SCMP_CMP(0, SCMP_CMP_EQ
, PR_SET_DUMPABLE
));
683 * Function responsible for setting up the fcntl64 syscall for
684 * the seccomp filter sandbox.
686 * NOTE: does not NEED to be here.. currently only occurs before filter; will
687 * keep just in case for the future.
690 sb_mprotect(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
695 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
696 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
));
700 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
701 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_NONE
));
709 * Function responsible for setting up the rt_sigprocmask syscall for
710 * the seccomp filter sandbox.
713 sb_rt_sigprocmask(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
718 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigprocmask
),
719 SCMP_CMP(0, SCMP_CMP_EQ
, SIG_UNBLOCK
));
723 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigprocmask
),
724 SCMP_CMP(0, SCMP_CMP_EQ
, SIG_SETMASK
));
732 * Function responsible for setting up the flock syscall for
733 * the seccomp filter sandbox.
735 * NOTE: does not need to be here, occurs before filter is applied.
738 sb_flock(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
743 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(flock
),
744 SCMP_CMP(1, SCMP_CMP_EQ
, LOCK_EX
|LOCK_NB
));
748 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(flock
),
749 SCMP_CMP(1, SCMP_CMP_EQ
, LOCK_UN
));
757 * Function responsible for setting up the futex syscall for
758 * the seccomp filter sandbox.
761 sb_futex(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
767 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
768 SCMP_CMP(1, SCMP_CMP_EQ
,
769 FUTEX_WAIT_BITSET_PRIVATE
|FUTEX_CLOCK_REALTIME
));
773 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
774 SCMP_CMP(1, SCMP_CMP_EQ
, FUTEX_WAKE_PRIVATE
));
778 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
),
779 SCMP_CMP(1, SCMP_CMP_EQ
, FUTEX_WAIT_PRIVATE
));
787 * Function responsible for setting up the mremap syscall for
788 * the seccomp filter sandbox.
790 * NOTE: so far only occurs before filter is applied.
793 sb_mremap(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
798 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mremap
),
799 SCMP_CMP(3, SCMP_CMP_EQ
, MREMAP_MAYMOVE
));
807 * Function responsible for setting up the poll syscall for
808 * the seccomp filter sandbox.
811 sb_poll(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
816 rc
= seccomp_rule_add_2(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(poll
),
817 SCMP_CMP(1, SCMP_CMP_EQ
, 1),
818 SCMP_CMP(2, SCMP_CMP_EQ
, 10));
827 * Function responsible for setting up the stat64 syscall for
828 * the seccomp filter sandbox.
831 sb_stat64(scmp_filter_ctx ctx
, sandbox_cfg_t
*filter
)
834 sandbox_cfg_t
*elem
= NULL
;
836 // for each dynamic parameter filters
837 for (elem
= filter
; elem
!= NULL
; elem
= elem
->next
) {
838 smp_param_t
*param
= elem
->param
;
840 if (param
!= NULL
&& param
->prot
== 1 && (param
->syscall
== SCMP_SYS(open
)
841 || param
->syscall
== SCMP_SYS(stat64
))) {
842 rc
= seccomp_rule_add_1(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(stat64
),
843 SCMP_CMP(0, SCMP_CMP_EQ
, param
->value
));
845 log_err(LD_BUG
,"(Sandbox) failed to add open syscall, received "
846 "libseccomp error %d", rc
);
857 * Array of function pointers responsible for filtering different syscalls at
860 static sandbox_filter_func_t filter_func
[] = {
896 sandbox_intern_string(const char *str
)
903 for (elem
= filter_dynamic
; elem
!= NULL
; elem
= elem
->next
) {
904 smp_param_t
*param
= elem
->param
;
907 if (!strcmp(str
, (char*)(param
->value
))) {
908 return (char*)param
->value
;
910 if (param
->value2
&& !strcmp(str
, (char*)param
->value2
)) {
911 return (char*)param
->value2
;
917 log_warn(LD_BUG
, "No interned sandbox parameter found for %s", str
);
923 prot_strings_helper(strmap_t
*locations
,
924 char **pr_mem_next_p
,
925 size_t *pr_mem_left_p
,
935 param_val
= (char*) *value_p
;
936 param_size
= strlen(param_val
) + 1;
937 location
= strmap_get(locations
, param_val
);
940 // We already interned this string.
942 *value_p
= (intptr_t) location
;
944 } else if (*pr_mem_left_p
>= param_size
) {
946 location
= *pr_mem_next_p
;
947 memcpy(location
, param_val
, param_size
);
949 // re-point el parameter to protected
951 *value_p
= (intptr_t) location
;
953 strmap_set(locations
, location
, location
); /* good real estate advice */
955 // move next available protected memory
956 *pr_mem_next_p
+= param_size
;
957 *pr_mem_left_p
-= param_size
;
960 log_err(LD_BUG
,"(Sandbox) insufficient protected memory!");
966 * Protects all the strings in the sandbox's parameter list configuration. It
967 * works by calculating the total amount of memory required by the parameter
968 * list, allocating the memory using mmap, and protecting it from writes with
972 prot_strings(scmp_filter_ctx ctx
, sandbox_cfg_t
* cfg
)
975 size_t pr_mem_size
= 0, pr_mem_left
= 0;
976 char *pr_mem_next
= NULL
, *pr_mem_base
;
977 sandbox_cfg_t
*el
= NULL
;
978 strmap_t
*locations
= NULL
;
980 // get total number of bytes required to mmap. (Overestimate.)
981 for (el
= cfg
; el
!= NULL
; el
= el
->next
) {
982 pr_mem_size
+= strlen((char*) el
->param
->value
) + 1;
983 if (el
->param
->value2
)
984 pr_mem_size
+= strlen((char*) el
->param
->value2
) + 1;
987 // allocate protected memory with MALLOC_MP_LIM canary
988 pr_mem_base
= (char*) mmap(NULL
, MALLOC_MP_LIM
+ pr_mem_size
,
989 PROT_READ
| PROT_WRITE
, MAP_PRIVATE
| MAP_ANON
, -1, 0);
990 if (pr_mem_base
== MAP_FAILED
) {
991 log_err(LD_BUG
,"(Sandbox) failed allocate protected memory! mmap: %s",
997 pr_mem_next
= pr_mem_base
+ MALLOC_MP_LIM
;
998 pr_mem_left
= pr_mem_size
;
1000 locations
= strmap_new();
1002 // change el value pointer to protected
1003 for (el
= cfg
; el
!= NULL
; el
= el
->next
) {
1004 if (prot_strings_helper(locations
, &pr_mem_next
, &pr_mem_left
,
1005 &el
->param
->value
) < 0) {
1009 if (prot_strings_helper(locations
, &pr_mem_next
, &pr_mem_left
,
1010 &el
->param
->value2
) < 0) {
1014 el
->param
->prot
= 1;
1017 // protecting from writes
1018 if (mprotect(pr_mem_base
, MALLOC_MP_LIM
+ pr_mem_size
, PROT_READ
)) {
1019 log_err(LD_BUG
,"(Sandbox) failed to protect memory! mprotect: %s",
1026 * Setting sandbox restrictions so the string memory cannot be tampered with
1028 // no mremap of the protected base address
1029 ret
= seccomp_rule_add_1(ctx
, SCMP_ACT_KILL
, SCMP_SYS(mremap
),
1030 SCMP_CMP(0, SCMP_CMP_EQ
, (intptr_t) pr_mem_base
));
1032 log_err(LD_BUG
,"(Sandbox) mremap protected memory filter fail!");
1036 // no munmap of the protected base address
1037 ret
= seccomp_rule_add_1(ctx
, SCMP_ACT_KILL
, SCMP_SYS(munmap
),
1038 SCMP_CMP(0, SCMP_CMP_EQ
, (intptr_t) pr_mem_base
));
1040 log_err(LD_BUG
,"(Sandbox) munmap protected memory filter fail!");
1045 * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
1046 * never over the memory region used by the protected strings.
1048 * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
1049 * had to be removed due to limitation of libseccomp regarding intervals.
1051 * There is a restriction on how much you can mprotect with R|W up to the
1052 * size of the canary.
1054 ret
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1055 SCMP_CMP(0, SCMP_CMP_LT
, (intptr_t) pr_mem_base
),
1056 SCMP_CMP(1, SCMP_CMP_LE
, MALLOC_MP_LIM
),
1057 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
));
1059 log_err(LD_BUG
,"(Sandbox) mprotect protected memory filter fail (LT)!");
1063 ret
= seccomp_rule_add_3(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
),
1064 SCMP_CMP(0, SCMP_CMP_GT
, (intptr_t) pr_mem_base
+ pr_mem_size
+
1066 SCMP_CMP(1, SCMP_CMP_LE
, MALLOC_MP_LIM
),
1067 SCMP_CMP(2, SCMP_CMP_EQ
, PROT_READ
|PROT_WRITE
));
1069 log_err(LD_BUG
,"(Sandbox) mprotect protected memory filter fail (GT)!");
1074 strmap_free(locations
, NULL
);
1079 * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
1080 * it's values according the the parameter list. All elements are initialised
1081 * with the 'prot' field set to false, as the pointer is not protected at this
1084 static sandbox_cfg_t
*
1085 new_element2(int syscall
, intptr_t value
, intptr_t value2
)
1087 smp_param_t
*param
= NULL
;
1089 sandbox_cfg_t
*elem
= tor_malloc_zero(sizeof(sandbox_cfg_t
));
1090 param
= elem
->param
= tor_malloc_zero(sizeof(smp_param_t
));
1092 param
->syscall
= syscall
;
1093 param
->value
= value
;
1094 param
->value2
= value2
;
1100 static sandbox_cfg_t
*
1101 new_element(int syscall
, intptr_t value
)
1103 return new_element2(syscall
, value
, 0);
1107 #define SCMP_stat SCMP_SYS(stat64)
1109 #define SCMP_stat SCMP_SYS(stat)
1113 sandbox_cfg_allow_stat_filename(sandbox_cfg_t
**cfg
, char *file
)
1115 sandbox_cfg_t
*elem
= NULL
;
1117 elem
= new_element(SCMP_stat
, (intptr_t)(void*) file
);
1119 log_err(LD_BUG
,"(Sandbox) failed to register parameter!");
1130 sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t
**cfg
, ...)
1138 while ((fn
= va_arg(ap
, char*)) != NULL
) {
1139 rc
= sandbox_cfg_allow_stat_filename(cfg
, fn
);
1141 log_err(LD_BUG
,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail");
1152 sandbox_cfg_allow_open_filename(sandbox_cfg_t
**cfg
, char *file
)
1154 sandbox_cfg_t
*elem
= NULL
;
1156 elem
= new_element(SCMP_SYS(open
), (intptr_t)(void *) file
);
1158 log_err(LD_BUG
,"(Sandbox) failed to register parameter!");
1169 sandbox_cfg_allow_rename(sandbox_cfg_t
**cfg
, char *file1
, char *file2
)
1171 sandbox_cfg_t
*elem
= NULL
;
1173 elem
= new_element2(SCMP_SYS(rename
),
1174 (intptr_t)(void *) file1
,
1175 (intptr_t)(void *) file2
);
1178 log_err(LD_BUG
,"(Sandbox) failed to register parameter!");
1189 sandbox_cfg_allow_open_filename_array(sandbox_cfg_t
**cfg
, ...)
1197 while ((fn
= va_arg(ap
, char*)) != NULL
) {
1198 rc
= sandbox_cfg_allow_open_filename(cfg
, fn
);
1200 log_err(LD_BUG
,"(Sandbox) sandbox_cfg_allow_open_filename_array fail");
1211 sandbox_cfg_allow_openat_filename(sandbox_cfg_t
**cfg
, char *file
)
1213 sandbox_cfg_t
*elem
= NULL
;
1215 elem
= new_element(SCMP_SYS(openat
), (intptr_t)(void *) file
);
1217 log_err(LD_BUG
,"(Sandbox) failed to register parameter!");
1228 sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t
**cfg
, ...)
1236 while ((fn
= va_arg(ap
, char*)) != NULL
) {
1237 rc
= sandbox_cfg_allow_openat_filename(cfg
, fn
);
1239 log_err(LD_BUG
,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail");
1251 sandbox_cfg_allow_execve(sandbox_cfg_t
**cfg
, const char *com
)
1253 sandbox_cfg_t
*elem
= NULL
;
1255 elem
= new_element(SCMP_SYS(execve
), (intptr_t)(void *) com
);
1257 log_err(LD_BUG
,"(Sandbox) failed to register parameter!");
1268 sandbox_cfg_allow_execve_array(sandbox_cfg_t
**cfg
, ...)
1276 while ((fn
= va_arg(ap
, char*)) != NULL
) {
1278 rc
= sandbox_cfg_allow_execve(cfg
, fn
);
1280 log_err(LD_BUG
,"(Sandbox) sandbox_cfg_allow_execve_array failed");
1292 sandbox_getaddrinfo(const char *name
, const char *servname
,
1293 const struct addrinfo
*hints
,
1294 struct addrinfo
**res
)
1298 if (servname
!= NULL
)
1303 for (el
= sb_addr_info
; el
; el
= el
->next
) {
1304 if (!strcmp(el
->name
, name
)) {
1305 *res
= tor_malloc(sizeof(struct addrinfo
));
1307 memcpy(*res
, el
->info
, sizeof(struct addrinfo
));
1308 /* XXXX What if there are multiple items in the list? */
1313 if (!sandbox_active
) {
1314 if (getaddrinfo(name
, NULL
, hints
, res
)) {
1315 log_err(LD_BUG
,"(Sandbox) getaddrinfo failed!");
1322 // getting here means something went wrong
1323 log_err(LD_BUG
,"(Sandbox) failed to get address %s!", name
);
1332 sandbox_add_addrinfo(const char* name
)
1335 struct addrinfo hints
;
1336 sb_addr_info_t
*el
= NULL
;
1338 el
= tor_malloc(sizeof(sb_addr_info_t
));
1340 memset(&hints
, 0, sizeof(hints
));
1341 hints
.ai_family
= AF_INET
;
1342 hints
.ai_socktype
= SOCK_STREAM
;
1344 ret
= getaddrinfo(name
, NULL
, &hints
, &(el
->info
));
1346 log_err(LD_BUG
,"(Sandbox) failed to getaddrinfo");
1352 el
->name
= tor_strdup(name
);
1353 el
->next
= sb_addr_info
;
1361 * Function responsible for going through the parameter syscall filters and
1362 * call each function pointer in the list.
1365 add_param_filter(scmp_filter_ctx ctx
, sandbox_cfg_t
* cfg
)
1371 for (i
= 0; i
< ARRAY_LENGTH(filter_func
); i
++) {
1372 if ((filter_func
[i
])(ctx
, cfg
)) {
1373 log_err(LD_BUG
,"(Sandbox) failed to add syscall %d, received libseccomp "
1383 * Function responsible of loading the libseccomp syscall filters which do not
1384 * have parameter filtering.
1387 add_noparam_filter(scmp_filter_ctx ctx
)
1392 // add general filters
1393 for (i
= 0; i
< ARRAY_LENGTH(filter_nopar_gen
); i
++) {
1394 rc
= seccomp_rule_add_0(ctx
, SCMP_ACT_ALLOW
, filter_nopar_gen
[i
]);
1396 log_err(LD_BUG
,"(Sandbox) failed to add syscall index %d (NR=%d), "
1397 "received libseccomp error %d", i
, filter_nopar_gen
[i
], rc
);
1406 * Function responsible for setting up and enabling a global syscall filter.
1407 * The function is a prototype developed for stage 1 of sandboxing Tor.
1408 * Returns 0 on success.
1411 install_syscall_filter(sandbox_cfg_t
* cfg
)
1414 scmp_filter_ctx ctx
;
1416 ctx
= seccomp_init(SCMP_ACT_TRAP
);
1418 log_err(LD_BUG
,"(Sandbox) failed to initialise libseccomp context");
1423 // protectign sandbox parameter strings
1424 if ((rc
= prot_strings(ctx
, cfg
))) {
1428 // add parameter filters
1429 if ((rc
= add_param_filter(ctx
, cfg
))) {
1430 log_err(LD_BUG
, "(Sandbox) failed to add param filters!");
1434 // adding filters with no parameters
1435 if ((rc
= add_noparam_filter(ctx
))) {
1436 log_err(LD_BUG
, "(Sandbox) failed to add param filters!");
1440 // loading the seccomp2 filter
1441 if ((rc
= seccomp_load(ctx
))) {
1442 log_err(LD_BUG
, "(Sandbox) failed to load!");
1446 // marking the sandbox as active
1450 seccomp_release(ctx
);
1451 return (rc
< 0 ? -rc
: rc
);
1454 #include "linux_syscalls.inc"
1456 get_syscall_name(int syscall_num
)
1459 for (i
= 0; SYSCALLS_BY_NUMBER
[i
].syscall_name
; ++i
) {
1460 if (SYSCALLS_BY_NUMBER
[i
].syscall_num
== syscall_num
)
1461 return SYSCALLS_BY_NUMBER
[i
].syscall_name
;
1465 static char syscall_name_buf
[64];
1466 format_dec_number_sigsafe(syscall_num
,
1467 syscall_name_buf
, sizeof(syscall_name_buf
));
1468 return syscall_name_buf
;
1472 #ifdef USE_BACKTRACE
1473 #define MAX_DEPTH 256
1474 static void *syscall_cb_buf
[MAX_DEPTH
];
1478 * Function called when a SIGSYS is caught by the application. It notifies the
1479 * user that an error has occurred and either terminates or allows the
1480 * application to continue execution, based on the DEBUGGING_CLOSE symbol.
1483 sigsys_debugging(int nr
, siginfo_t
*info
, void *void_context
)
1485 ucontext_t
*ctx
= (ucontext_t
*) (void_context
);
1486 const char *syscall_name
;
1488 #ifdef USE_BACKTRACE
1491 const int *fds
= NULL
;
1496 if (info
->si_code
!= SYS_SECCOMP
)
1502 syscall
= (int) ctx
->uc_mcontext
.gregs
[REG_SYSCALL
];
1504 #ifdef USE_BACKTRACE
1505 depth
= backtrace(syscall_cb_buf
, MAX_DEPTH
);
1506 /* Clean up the top stack frame so we get the real function
1507 * name for the most recently failing function. */
1508 clean_backtrace(syscall_cb_buf
, depth
, ctx
);
1511 syscall_name
= get_syscall_name(syscall
);
1513 tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1518 #ifdef USE_BACKTRACE
1519 n_fds
= tor_log_get_sigsafe_err_fds(&fds
);
1520 for (i
=0; i
< n_fds
; ++i
)
1521 backtrace_symbols_fd(syscall_cb_buf
, depth
, fds
[i
]);
1524 #if defined(DEBUGGING_CLOSE)
1526 #endif // DEBUGGING_CLOSE
1530 * Function that adds a handler for SIGSYS, which is the signal thrown
1531 * when the application is issuing a syscall which is not allowed. The
1532 * main purpose of this function is to help with debugging by identifying
1533 * filtered syscalls.
1536 install_sigsys_debugging(void)
1538 struct sigaction act
;
1541 memset(&act
, 0, sizeof(act
));
1543 sigaddset(&mask
, SIGSYS
);
1545 act
.sa_sigaction
= &sigsys_debugging
;
1546 act
.sa_flags
= SA_SIGINFO
;
1547 if (sigaction(SIGSYS
, &act
, NULL
) < 0) {
1548 log_err(LD_BUG
,"(Sandbox) Failed to register SIGSYS signal handler");
1552 if (sigprocmask(SIG_UNBLOCK
, &mask
, NULL
)) {
1553 log_err(LD_BUG
,"(Sandbox) Failed call to sigprocmask()");
1561 * Function responsible of registering the sandbox_cfg_t list of parameter
1562 * syscall filters to the existing parameter list. This is used for incipient
1563 * multiple-sandbox support.
1566 register_cfg(sandbox_cfg_t
* cfg
)
1568 sandbox_cfg_t
*elem
= NULL
;
1570 if (filter_dynamic
== NULL
) {
1571 filter_dynamic
= cfg
;
1575 for (elem
= filter_dynamic
; elem
->next
!= NULL
; elem
= elem
->next
)
1583 #endif // USE_LIBSECCOMP
1585 #ifdef USE_LIBSECCOMP
1587 * Initialises the syscall sandbox filter for any linux architecture, taking
1588 * into account various available features for different linux flavours.
1591 initialise_libseccomp_sandbox(sandbox_cfg_t
* cfg
)
1593 if (install_sigsys_debugging())
1596 if (install_syscall_filter(cfg
))
1599 if (register_cfg(cfg
))
1606 sandbox_is_active(void)
1608 return sandbox_active
!= 0;
1610 #endif // USE_LIBSECCOMP
1613 sandbox_cfg_new(void)
1619 sandbox_init(sandbox_cfg_t
*cfg
)
1621 #if defined(USE_LIBSECCOMP)
1622 return initialise_libseccomp_sandbox(cfg
);
1624 #elif defined(__linux__)
1626 log_warn(LD_GENERAL
,
1627 "This version of Tor was built without support for sandboxing. To "
1628 "build with support for sandboxing on Linux, you must have "
1629 "libseccomp and its necessary header files (e.g. seccomp.h).");
1634 log_warn(LD_GENERAL
,
1635 "Currently, sandboxing is only implemented on Linux. The feature "
1636 "is disabled on your platform.");
1641 #ifndef USE_LIBSECCOMP
1643 sandbox_cfg_allow_open_filename(sandbox_cfg_t
**cfg
, char *file
)
1645 (void)cfg
; (void)file
;
1650 sandbox_cfg_allow_open_filename_array(sandbox_cfg_t
**cfg
, ...)
1657 sandbox_cfg_allow_openat_filename(sandbox_cfg_t
**cfg
, char *file
)
1659 (void)cfg
; (void)file
;
1664 sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t
**cfg
, ...)
1672 sandbox_cfg_allow_execve(sandbox_cfg_t
**cfg
, const char *com
)
1674 (void)cfg
; (void)com
;
1679 sandbox_cfg_allow_execve_array(sandbox_cfg_t
**cfg
, ...)
1687 sandbox_cfg_allow_stat_filename(sandbox_cfg_t
**cfg
, char *file
)
1689 (void)cfg
; (void)file
;
1694 sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t
**cfg
, ...)
1701 sandbox_cfg_allow_rename(sandbox_cfg_t
**cfg
, char *file1
, char *file2
)
1703 (void)cfg
; (void)file1
; (void)file2
;
1708 sandbox_is_active(void)