Fix sandbox use with systemd. bug 16212.
[tor.git] / src / common / sandbox.c
bloba32bd0d901624ff89e669d9cd06c335be016873c
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-2015, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file sandbox.c
9 * \brief Code to enable sandboxing.
10 **/
12 #include "orconfig.h"
14 #ifndef _LARGEFILE64_SOURCE
15 /**
16 * Temporarily required for O_LARGEFILE flag. Needs to be removed
17 * with the libevent fix.
19 #define _LARGEFILE64_SOURCE
20 #endif
22 /** Malloc mprotect limit in bytes. */
23 #define MALLOC_MP_LIM 1048576
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
29 #include "sandbox.h"
30 #include "container.h"
31 #include "torlog.h"
32 #include "torint.h"
33 #include "util.h"
34 #include "tor_queue.h"
36 #include "ht.h"
38 #define DEBUGGING_CLOSE
40 #if defined(USE_LIBSECCOMP)
42 #define _GNU_SOURCE
44 #include <sys/mman.h>
45 #include <sys/syscall.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/epoll.h>
49 #include <sys/prctl.h>
50 #include <linux/futex.h>
51 #include <bits/signum.h>
53 #include <stdarg.h>
54 #include <seccomp.h>
55 #include <signal.h>
56 #include <unistd.h>
57 #include <fcntl.h>
58 #include <time.h>
59 #include <poll.h>
61 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
62 #include <linux/netfilter_ipv4.h>
63 #endif
64 #ifdef HAVE_LINUX_IF_H
65 #include <linux/if.h>
66 #endif
67 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
68 #include <linux/netfilter_ipv6/ip6_tables.h>
69 #endif
71 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
72 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
73 #define USE_BACKTRACE
74 #define EXPOSE_CLEAN_BACKTRACE
75 #include "backtrace.h"
76 #endif
78 #ifdef USE_BACKTRACE
79 #include <execinfo.h>
80 #endif
82 /**
83 * Linux 32 bit definitions
85 #if defined(__i386__)
87 #define REG_SYSCALL REG_EAX
88 #define M_SYSCALL gregs[REG_SYSCALL]
90 /**
91 * Linux 64 bit definitions
93 #elif defined(__x86_64__)
95 #define REG_SYSCALL REG_RAX
96 #define M_SYSCALL gregs[REG_SYSCALL]
98 #elif defined(__arm__)
100 #define M_SYSCALL arm_r7
102 #endif
104 /**Determines if at least one sandbox is active.*/
105 static int sandbox_active = 0;
106 /** Holds the parameter list configuration for the sandbox.*/
107 static sandbox_cfg_t *filter_dynamic = NULL;
109 #undef SCMP_CMP
110 #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
111 #define SCMP_CMP_STR(a,b,c) \
112 ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
113 #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
114 /* We use a wrapper here because these masked comparisons seem to be pretty
115 * verbose. Also, it's important to cast to scmp_datum_t before negating the
116 * mask, since otherwise the negation might get applied to a 32 bit value, and
117 * the high bits of the value might get masked out improperly. */
118 #define SCMP_CMP_MASKED(a,b,c) \
119 SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
121 /** Variable used for storing all syscall numbers that will be allowed with the
122 * stage 1 general Tor sandbox.
124 static int filter_nopar_gen[] = {
125 SCMP_SYS(access),
126 SCMP_SYS(brk),
127 SCMP_SYS(clock_gettime),
128 SCMP_SYS(close),
129 SCMP_SYS(clone),
130 SCMP_SYS(epoll_create),
131 SCMP_SYS(epoll_wait),
132 SCMP_SYS(fcntl),
133 SCMP_SYS(fstat),
134 #ifdef __NR_fstat64
135 SCMP_SYS(fstat64),
136 #endif
137 SCMP_SYS(getdents64),
138 SCMP_SYS(getegid),
139 #ifdef __NR_getegid32
140 SCMP_SYS(getegid32),
141 #endif
142 SCMP_SYS(geteuid),
143 #ifdef __NR_geteuid32
144 SCMP_SYS(geteuid32),
145 #endif
146 SCMP_SYS(getgid),
147 #ifdef __NR_getgid32
148 SCMP_SYS(getgid32),
149 #endif
150 #ifdef __NR_getrlimit
151 SCMP_SYS(getrlimit),
152 #endif
153 SCMP_SYS(gettimeofday),
154 SCMP_SYS(gettid),
155 SCMP_SYS(getuid),
156 #ifdef __NR_getuid32
157 SCMP_SYS(getuid32),
158 #endif
159 SCMP_SYS(lseek),
160 #ifdef __NR__llseek
161 SCMP_SYS(_llseek),
162 #endif
163 SCMP_SYS(mkdir),
164 SCMP_SYS(mlockall),
165 #ifdef __NR_mmap
166 /* XXXX restrict this in the same ways as mmap2 */
167 SCMP_SYS(mmap),
168 #endif
169 SCMP_SYS(munmap),
170 SCMP_SYS(read),
171 SCMP_SYS(rt_sigreturn),
172 SCMP_SYS(sched_getaffinity),
173 SCMP_SYS(sendmsg),
174 SCMP_SYS(set_robust_list),
175 #ifdef __NR_sigreturn
176 SCMP_SYS(sigreturn),
177 #endif
178 SCMP_SYS(stat),
179 SCMP_SYS(uname),
180 SCMP_SYS(wait4),
181 SCMP_SYS(write),
182 SCMP_SYS(writev),
183 SCMP_SYS(exit_group),
184 SCMP_SYS(exit),
186 SCMP_SYS(madvise),
187 #ifdef __NR_stat64
188 // getaddrinfo uses this..
189 SCMP_SYS(stat64),
190 #endif
193 * These socket syscalls are not required on x86_64 and not supported with
194 * some libseccomp versions (eg: 1.0.1)
196 #if defined(__i386)
197 SCMP_SYS(recv),
198 SCMP_SYS(send),
199 #endif
201 // socket syscalls
202 SCMP_SYS(bind),
203 SCMP_SYS(listen),
204 SCMP_SYS(connect),
205 SCMP_SYS(getsockname),
206 SCMP_SYS(recvmsg),
207 SCMP_SYS(recvfrom),
208 SCMP_SYS(sendto),
209 SCMP_SYS(unlink)
212 /* These macros help avoid the error where the number of filters we add on a
213 * single rule don't match the arg_cnt param. */
214 #define seccomp_rule_add_0(ctx,act,call) \
215 seccomp_rule_add((ctx),(act),(call),0)
216 #define seccomp_rule_add_1(ctx,act,call,f1) \
217 seccomp_rule_add((ctx),(act),(call),1,(f1))
218 #define seccomp_rule_add_2(ctx,act,call,f1,f2) \
219 seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
220 #define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
221 seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
222 #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
223 seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
226 * Function responsible for setting up the rt_sigaction syscall for
227 * the seccomp filter sandbox.
229 static int
230 sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
232 unsigned i;
233 int rc;
234 int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
235 #ifdef SIGXFSZ
236 SIGXFSZ
237 #endif
239 (void) filter;
241 for (i = 0; i < ARRAY_LENGTH(param); i++) {
242 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
243 SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
244 if (rc)
245 break;
248 return rc;
251 #if 0
253 * Function responsible for setting up the execve syscall for
254 * the seccomp filter sandbox.
256 static int
257 sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
259 int rc;
260 sandbox_cfg_t *elem = NULL;
262 // for each dynamic parameter filters
263 for (elem = filter; elem != NULL; elem = elem->next) {
264 smp_param_t *param = elem->param;
266 if (param != NULL && param->prot == 1 && param->syscall
267 == SCMP_SYS(execve)) {
268 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve),
269 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
270 if (rc != 0) {
271 log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received "
272 "libseccomp error %d", rc);
273 return rc;
278 return 0;
280 #endif
283 * Function responsible for setting up the time syscall for
284 * the seccomp filter sandbox.
286 static int
287 sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
289 (void) filter;
290 #ifdef __NR_time
291 return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
292 SCMP_CMP(0, SCMP_CMP_EQ, 0));
293 #else
294 return 0;
295 #endif
299 * Function responsible for setting up the accept4 syscall for
300 * the seccomp filter sandbox.
302 static int
303 sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
305 int rc = 0;
306 (void)filter;
308 #ifdef __i386__
309 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
310 SCMP_CMP(0, SCMP_CMP_EQ, 18));
311 if (rc) {
312 return rc;
314 #endif
316 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
317 SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
318 if (rc) {
319 return rc;
322 return 0;
325 #ifdef __NR_mmap2
327 * Function responsible for setting up the mmap2 syscall for
328 * the seccomp filter sandbox.
330 static int
331 sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
333 int rc = 0;
334 (void)filter;
336 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
337 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
338 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
339 if (rc) {
340 return rc;
343 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
344 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
345 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
346 if (rc) {
347 return rc;
350 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
351 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
352 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
353 if (rc) {
354 return rc;
357 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
358 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
359 SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
360 if (rc) {
361 return rc;
364 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
365 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
366 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
367 if (rc) {
368 return rc;
371 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
372 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
373 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
374 if (rc) {
375 return rc;
378 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
379 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
380 SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
381 if (rc) {
382 return rc;
385 return 0;
387 #endif
390 * Function responsible for setting up the open syscall for
391 * the seccomp filter sandbox.
393 static int
394 sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
396 int rc;
397 sandbox_cfg_t *elem = NULL;
399 // for each dynamic parameter filters
400 for (elem = filter; elem != NULL; elem = elem->next) {
401 smp_param_t *param = elem->param;
403 if (param != NULL && param->prot == 1 && param->syscall
404 == SCMP_SYS(open)) {
405 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
406 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
407 if (rc != 0) {
408 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
409 "libseccomp error %d", rc);
410 return rc;
415 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open),
416 SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY, O_RDONLY));
417 if (rc != 0) {
418 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp "
419 "error %d", rc);
420 return rc;
423 return 0;
426 static int
427 sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
429 int rc;
430 (void) filter;
431 (void) ctx;
433 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl));
434 if (rc != 0) {
435 log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, "
436 "received libseccomp error %d", rc);
437 return rc;
440 return 0;
444 * Function responsible for setting up the rename syscall for
445 * the seccomp filter sandbox.
447 static int
448 sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
450 int rc;
451 sandbox_cfg_t *elem = NULL;
453 // for each dynamic parameter filters
454 for (elem = filter; elem != NULL; elem = elem->next) {
455 smp_param_t *param = elem->param;
457 if (param != NULL && param->prot == 1 &&
458 param->syscall == SCMP_SYS(rename)) {
460 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
461 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
462 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
463 if (rc != 0) {
464 log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
465 "libseccomp error %d", rc);
466 return rc;
471 return 0;
475 * Function responsible for setting up the openat syscall for
476 * the seccomp filter sandbox.
478 static int
479 sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
481 int rc;
482 sandbox_cfg_t *elem = NULL;
484 // for each dynamic parameter filters
485 for (elem = filter; elem != NULL; elem = elem->next) {
486 smp_param_t *param = elem->param;
488 if (param != NULL && param->prot == 1 && param->syscall
489 == SCMP_SYS(openat)) {
490 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
491 SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD),
492 SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
493 SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
494 O_CLOEXEC));
495 if (rc != 0) {
496 log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
497 "libseccomp error %d", rc);
498 return rc;
503 return 0;
507 * Function responsible for setting up the socket syscall for
508 * the seccomp filter sandbox.
510 static int
511 sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
513 int rc = 0;
514 int i;
515 (void) filter;
517 #ifdef __i386__
518 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
519 if (rc)
520 return rc;
521 #endif
523 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
524 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
525 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
526 if (rc)
527 return rc;
529 for (i = 0; i < 2; ++i) {
530 const int pf = i ? PF_INET : PF_INET6;
532 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
533 SCMP_CMP(0, SCMP_CMP_EQ, pf),
534 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
535 SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP));
536 if (rc)
537 return rc;
539 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
540 SCMP_CMP(0, SCMP_CMP_EQ, pf),
541 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
542 SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
543 if (rc)
544 return rc;
547 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
548 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
549 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
550 SCMP_CMP(2, SCMP_CMP_EQ, 0));
551 if (rc)
552 return rc;
554 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
555 SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
556 SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
557 SCMP_CMP(2, SCMP_CMP_EQ, 0));
558 if (rc)
559 return rc;
561 rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
562 SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
563 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW),
564 SCMP_CMP(2, SCMP_CMP_EQ, 0));
565 if (rc)
566 return rc;
568 return 0;
572 * Function responsible for setting up the socketpair syscall for
573 * the seccomp filter sandbox.
575 static int
576 sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
578 int rc = 0;
579 (void) filter;
581 #ifdef __i386__
582 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
583 if (rc)
584 return rc;
585 #endif
587 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
588 SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
589 SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
590 if (rc)
591 return rc;
593 return 0;
597 * Function responsible for setting up the setsockopt syscall for
598 * the seccomp filter sandbox.
600 static int
601 sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
603 int rc = 0;
604 (void) filter;
606 #ifdef __i386__
607 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
608 if (rc)
609 return rc;
610 #endif
612 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
613 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
614 SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
615 if (rc)
616 return rc;
618 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
619 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
620 SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
621 if (rc)
622 return rc;
624 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
625 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
626 SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
627 if (rc)
628 return rc;
630 #ifdef IP_TRANSPARENT
631 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
632 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
633 SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
634 if (rc)
635 return rc;
636 #endif
638 return 0;
642 * Function responsible for setting up the getsockopt syscall for
643 * the seccomp filter sandbox.
645 static int
646 sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
648 int rc = 0;
649 (void) filter;
651 #ifdef __i386__
652 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
653 if (rc)
654 return rc;
655 #endif
657 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
658 SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
659 SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
660 if (rc)
661 return rc;
663 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
664 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
665 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
666 SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
667 if (rc)
668 return rc;
669 #endif
671 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
672 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
673 SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
674 SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
675 if (rc)
676 return rc;
677 #endif
679 return 0;
682 #ifdef __NR_fcntl64
684 * Function responsible for setting up the fcntl64 syscall for
685 * the seccomp filter sandbox.
687 static int
688 sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
690 int rc = 0;
691 (void) filter;
693 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
694 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
695 if (rc)
696 return rc;
698 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
699 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
700 SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
701 if (rc)
702 return rc;
704 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
705 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
706 if (rc)
707 return rc;
709 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
710 SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
711 SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
712 if (rc)
713 return rc;
715 return 0;
717 #endif
720 * Function responsible for setting up the epoll_ctl syscall for
721 * the seccomp filter sandbox.
723 * Note: basically allows everything but will keep for now..
725 static int
726 sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
728 int rc = 0;
729 (void) filter;
731 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
732 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
733 if (rc)
734 return rc;
736 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
737 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
738 if (rc)
739 return rc;
741 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
742 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
743 if (rc)
744 return rc;
746 return 0;
750 * Function responsible for setting up the fcntl64 syscall for
751 * the seccomp filter sandbox.
753 * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
754 * to be whitelisted in this function.
756 static int
757 sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
759 int rc = 0;
760 (void) filter;
762 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
763 SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
764 if (rc)
765 return rc;
767 return 0;
771 * Function responsible for setting up the fcntl64 syscall for
772 * the seccomp filter sandbox.
774 * NOTE: does not NEED to be here.. currently only occurs before filter; will
775 * keep just in case for the future.
777 static int
778 sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
780 int rc = 0;
781 (void) filter;
783 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
784 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
785 if (rc)
786 return rc;
788 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
789 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
790 if (rc)
791 return rc;
793 return 0;
797 * Function responsible for setting up the rt_sigprocmask syscall for
798 * the seccomp filter sandbox.
800 static int
801 sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
803 int rc = 0;
804 (void) filter;
806 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
807 SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
808 if (rc)
809 return rc;
811 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
812 SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
813 if (rc)
814 return rc;
816 return 0;
820 * Function responsible for setting up the flock syscall for
821 * the seccomp filter sandbox.
823 * NOTE: does not need to be here, occurs before filter is applied.
825 static int
826 sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
828 int rc = 0;
829 (void) filter;
831 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
832 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
833 if (rc)
834 return rc;
836 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
837 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
838 if (rc)
839 return rc;
841 return 0;
845 * Function responsible for setting up the futex syscall for
846 * the seccomp filter sandbox.
848 static int
849 sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
851 int rc = 0;
852 (void) filter;
854 // can remove
855 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
856 SCMP_CMP(1, SCMP_CMP_EQ,
857 FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
858 if (rc)
859 return rc;
861 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
862 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
863 if (rc)
864 return rc;
866 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
867 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
868 if (rc)
869 return rc;
871 return 0;
875 * Function responsible for setting up the mremap syscall for
876 * the seccomp filter sandbox.
878 * NOTE: so far only occurs before filter is applied.
880 static int
881 sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
883 int rc = 0;
884 (void) filter;
886 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
887 SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
888 if (rc)
889 return rc;
891 return 0;
895 * Function responsible for setting up the poll syscall for
896 * the seccomp filter sandbox.
898 static int
899 sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
901 int rc = 0;
902 (void) filter;
904 rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll),
905 SCMP_CMP(1, SCMP_CMP_EQ, 1),
906 SCMP_CMP(2, SCMP_CMP_EQ, 10));
907 if (rc)
908 return rc;
910 return 0;
913 #ifdef __NR_stat64
915 * Function responsible for setting up the stat64 syscall for
916 * the seccomp filter sandbox.
918 static int
919 sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
921 int rc = 0;
922 sandbox_cfg_t *elem = NULL;
924 // for each dynamic parameter filters
925 for (elem = filter; elem != NULL; elem = elem->next) {
926 smp_param_t *param = elem->param;
928 if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
929 || param->syscall == SCMP_SYS(stat64))) {
930 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
931 SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
932 if (rc != 0) {
933 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
934 "libseccomp error %d", rc);
935 return rc;
940 return 0;
942 #endif
945 * Array of function pointers responsible for filtering different syscalls at
946 * a parameter level.
948 static sandbox_filter_func_t filter_func[] = {
949 sb_rt_sigaction,
950 sb_rt_sigprocmask,
951 #if 0
952 sb_execve,
953 #endif
954 sb_time,
955 sb_accept4,
956 #ifdef __NR_mmap2
957 sb_mmap2,
958 #endif
959 sb_open,
960 sb_openat,
961 sb__sysctl,
962 sb_rename,
963 #ifdef __NR_fcntl64
964 sb_fcntl64,
965 #endif
966 sb_epoll_ctl,
967 sb_prctl,
968 sb_mprotect,
969 sb_flock,
970 sb_futex,
971 sb_mremap,
972 sb_poll,
973 #ifdef __NR_stat64
974 sb_stat64,
975 #endif
977 sb_socket,
978 sb_setsockopt,
979 sb_getsockopt,
980 sb_socketpair
983 const char *
984 sandbox_intern_string(const char *str)
986 sandbox_cfg_t *elem;
988 if (str == NULL)
989 return NULL;
991 for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
992 smp_param_t *param = elem->param;
994 if (param->prot) {
995 if (!strcmp(str, (char*)(param->value))) {
996 return (char*)param->value;
998 if (param->value2 && !strcmp(str, (char*)param->value2)) {
999 return (char*)param->value2;
1004 if (sandbox_active)
1005 log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
1006 return str;
1009 /** DOCDOC */
1010 static int
1011 prot_strings_helper(strmap_t *locations,
1012 char **pr_mem_next_p,
1013 size_t *pr_mem_left_p,
1014 char **value_p)
1016 char *param_val;
1017 size_t param_size;
1018 void *location;
1020 if (*value_p == 0)
1021 return 0;
1023 param_val = (char*) *value_p;
1024 param_size = strlen(param_val) + 1;
1025 location = strmap_get(locations, param_val);
1027 if (location) {
1028 // We already interned this string.
1029 tor_free(param_val);
1030 *value_p = location;
1031 return 0;
1032 } else if (*pr_mem_left_p >= param_size) {
1033 // copy to protected
1034 location = *pr_mem_next_p;
1035 memcpy(location, param_val, param_size);
1037 // re-point el parameter to protected
1038 tor_free(param_val);
1039 *value_p = location;
1041 strmap_set(locations, location, location); /* good real estate advice */
1043 // move next available protected memory
1044 *pr_mem_next_p += param_size;
1045 *pr_mem_left_p -= param_size;
1046 return 0;
1047 } else {
1048 log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
1049 return -1;
1054 * Protects all the strings in the sandbox's parameter list configuration. It
1055 * works by calculating the total amount of memory required by the parameter
1056 * list, allocating the memory using mmap, and protecting it from writes with
1057 * mprotect().
1059 static int
1060 prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1062 int ret = 0;
1063 size_t pr_mem_size = 0, pr_mem_left = 0;
1064 char *pr_mem_next = NULL, *pr_mem_base;
1065 sandbox_cfg_t *el = NULL;
1066 strmap_t *locations = NULL;
1068 // get total number of bytes required to mmap. (Overestimate.)
1069 for (el = cfg; el != NULL; el = el->next) {
1070 pr_mem_size += strlen((char*) el->param->value) + 1;
1071 if (el->param->value2)
1072 pr_mem_size += strlen((char*) el->param->value2) + 1;
1075 // allocate protected memory with MALLOC_MP_LIM canary
1076 pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
1077 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1078 if (pr_mem_base == MAP_FAILED) {
1079 log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
1080 strerror(errno));
1081 ret = -1;
1082 goto out;
1085 pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
1086 pr_mem_left = pr_mem_size;
1088 locations = strmap_new();
1090 // change el value pointer to protected
1091 for (el = cfg; el != NULL; el = el->next) {
1092 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1093 &el->param->value) < 0) {
1094 ret = -2;
1095 goto out;
1097 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1098 &el->param->value2) < 0) {
1099 ret = -2;
1100 goto out;
1102 el->param->prot = 1;
1105 // protecting from writes
1106 if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1107 log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
1108 strerror(errno));
1109 ret = -3;
1110 goto out;
1114 * Setting sandbox restrictions so the string memory cannot be tampered with
1116 // no mremap of the protected base address
1117 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
1118 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1119 if (ret) {
1120 log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
1121 goto out;
1124 // no munmap of the protected base address
1125 ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
1126 SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1127 if (ret) {
1128 log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
1129 goto out;
1133 * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
1134 * never over the memory region used by the protected strings.
1136 * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
1137 * had to be removed due to limitation of libseccomp regarding intervals.
1139 * There is a restriction on how much you can mprotect with R|W up to the
1140 * size of the canary.
1142 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1143 SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
1144 SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1145 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1146 if (ret) {
1147 log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
1148 goto out;
1151 ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1152 SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
1153 MALLOC_MP_LIM),
1154 SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1155 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1156 if (ret) {
1157 log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
1158 goto out;
1161 out:
1162 strmap_free(locations, NULL);
1163 return ret;
1167 * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
1168 * it's values according the the parameter list. All elements are initialised
1169 * with the 'prot' field set to false, as the pointer is not protected at this
1170 * point.
1172 static sandbox_cfg_t*
1173 new_element2(int syscall, char *value, char *value2)
1175 smp_param_t *param = NULL;
1177 sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
1178 param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
1180 param->syscall = syscall;
1181 param->value = value;
1182 param->value2 = value2;
1183 param->prot = 0;
1185 return elem;
1188 static sandbox_cfg_t*
1189 new_element(int syscall, char *value)
1191 return new_element2(syscall, value, NULL);
1194 #ifdef __NR_stat64
1195 #define SCMP_stat SCMP_SYS(stat64)
1196 #else
1197 #define SCMP_stat SCMP_SYS(stat)
1198 #endif
1201 sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1203 sandbox_cfg_t *elem = NULL;
1205 elem = new_element(SCMP_stat, file);
1206 if (!elem) {
1207 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1208 return -1;
1211 elem->next = *cfg;
1212 *cfg = elem;
1214 return 0;
1218 sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1220 sandbox_cfg_t *elem = NULL;
1222 elem = new_element(SCMP_SYS(open), file);
1223 if (!elem) {
1224 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1225 return -1;
1228 elem->next = *cfg;
1229 *cfg = elem;
1231 return 0;
1235 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1237 sandbox_cfg_t *elem = NULL;
1239 elem = new_element2(SCMP_SYS(rename), file1, file2);
1241 if (!elem) {
1242 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1243 return -1;
1246 elem->next = *cfg;
1247 *cfg = elem;
1249 return 0;
1253 sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1255 sandbox_cfg_t *elem = NULL;
1257 elem = new_element(SCMP_SYS(openat), file);
1258 if (!elem) {
1259 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1260 return -1;
1263 elem->next = *cfg;
1264 *cfg = elem;
1266 return 0;
1269 #if 0
1271 sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com)
1273 sandbox_cfg_t *elem = NULL;
1275 elem = new_element(SCMP_SYS(execve), com);
1276 if (!elem) {
1277 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1278 return -1;
1281 elem->next = *cfg;
1282 *cfg = elem;
1284 return 0;
1287 #endif
1289 /** Cache entry for getaddrinfo results; used when sandboxing is implemented
1290 * so that we can consult the cache when the sandbox prevents us from doing
1291 * getaddrinfo.
1293 * We support only a limited range of getaddrinfo calls, where servname is null
1294 * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
1296 typedef struct cached_getaddrinfo_item_t {
1297 HT_ENTRY(cached_getaddrinfo_item_t) node;
1298 char *name;
1299 int family;
1300 /** set if no error; otherwise NULL */
1301 struct addrinfo *res;
1302 /** 0 for no error; otherwise an EAI_* value */
1303 int err;
1304 } cached_getaddrinfo_item_t;
1306 static unsigned
1307 cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
1309 return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
1312 static unsigned
1313 cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
1314 const cached_getaddrinfo_item_t *b)
1316 return (a->family == b->family) && 0 == strcmp(a->name, b->name);
1319 static void
1320 cached_getaddrinfo_item_free(cached_getaddrinfo_item_t *item)
1322 if (item == NULL)
1323 return;
1325 tor_free(item->name);
1326 if (item->res)
1327 freeaddrinfo(item->res);
1328 tor_free(item);
1331 static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
1332 getaddrinfo_cache = HT_INITIALIZER();
1334 HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
1335 cached_getaddrinfo_item_hash,
1336 cached_getaddrinfo_items_eq);
1337 HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
1338 cached_getaddrinfo_item_hash,
1339 cached_getaddrinfo_items_eq,
1340 0.6, tor_reallocarray_, tor_free_)
1342 /** If true, don't try to cache getaddrinfo results. */
1343 static int sandbox_getaddrinfo_cache_disabled = 0;
1345 /** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
1346 * tor-resolve, when we have no intention of initializing crypto or of
1347 * installing the sandbox.*/
1348 void
1349 sandbox_disable_getaddrinfo_cache(void)
1351 sandbox_getaddrinfo_cache_disabled = 1;
1354 void
1355 sandbox_freeaddrinfo(struct addrinfo *ai)
1357 if (sandbox_getaddrinfo_cache_disabled)
1358 freeaddrinfo(ai);
1362 sandbox_getaddrinfo(const char *name, const char *servname,
1363 const struct addrinfo *hints,
1364 struct addrinfo **res)
1366 int err;
1367 struct cached_getaddrinfo_item_t search, *item;
1369 if (sandbox_getaddrinfo_cache_disabled) {
1370 return getaddrinfo(name, NULL, hints, res);
1373 if (servname != NULL) {
1374 log_warn(LD_BUG, "called with non-NULL servname");
1375 return EAI_NONAME;
1377 if (name == NULL) {
1378 log_warn(LD_BUG, "called with NULL name");
1379 return EAI_NONAME;
1382 *res = NULL;
1384 memset(&search, 0, sizeof(search));
1385 search.name = (char *) name;
1386 search.family = hints ? hints->ai_family : AF_UNSPEC;
1387 item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
1389 if (! sandbox_is_active()) {
1390 /* If the sandbox is not turned on yet, then getaddrinfo and store the
1391 result. */
1393 err = getaddrinfo(name, NULL, hints, res);
1394 log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
1396 if (! item) {
1397 item = tor_malloc_zero(sizeof(*item));
1398 item->name = tor_strdup(name);
1399 item->family = hints ? hints->ai_family : AF_UNSPEC;
1400 HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
1403 if (item->res) {
1404 freeaddrinfo(item->res);
1405 item->res = NULL;
1407 item->res = *res;
1408 item->err = err;
1409 return err;
1412 /* Otherwise, the sanbox is on. If we have an item, yield its cached
1413 result. */
1414 if (item) {
1415 *res = item->res;
1416 return item->err;
1419 /* getting here means something went wrong */
1420 log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
1421 return EAI_NONAME;
1425 sandbox_add_addrinfo(const char *name)
1427 struct addrinfo *res;
1428 struct addrinfo hints;
1429 int i;
1430 static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
1432 memset(&hints, 0, sizeof(hints));
1433 hints.ai_socktype = SOCK_STREAM;
1434 for (i = 0; i < 3; ++i) {
1435 hints.ai_family = families[i];
1437 res = NULL;
1438 (void) sandbox_getaddrinfo(name, NULL, &hints, &res);
1439 if (res)
1440 sandbox_freeaddrinfo(res);
1443 return 0;
1446 void
1447 sandbox_free_getaddrinfo_cache(void)
1449 cached_getaddrinfo_item_t **next, **item;
1451 for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
1452 item;
1453 item = next) {
1454 next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
1455 cached_getaddrinfo_item_free(*item);
1458 HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
1462 * Function responsible for going through the parameter syscall filters and
1463 * call each function pointer in the list.
1465 static int
1466 add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1468 unsigned i;
1469 int rc = 0;
1471 // function pointer
1472 for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
1473 if ((filter_func[i])(ctx, cfg)) {
1474 log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
1475 "error %d", i, rc);
1476 return rc;
1480 return 0;
1484 * Function responsible of loading the libseccomp syscall filters which do not
1485 * have parameter filtering.
1487 static int
1488 add_noparam_filter(scmp_filter_ctx ctx)
1490 unsigned i;
1491 int rc = 0;
1493 // add general filters
1494 for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
1495 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
1496 if (rc != 0) {
1497 log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), "
1498 "received libseccomp error %d", i, filter_nopar_gen[i], rc);
1499 return rc;
1503 return 0;
1507 * Function responsible for setting up and enabling a global syscall filter.
1508 * The function is a prototype developed for stage 1 of sandboxing Tor.
1509 * Returns 0 on success.
1511 static int
1512 install_syscall_filter(sandbox_cfg_t* cfg)
1514 int rc = 0;
1515 scmp_filter_ctx ctx;
1517 ctx = seccomp_init(SCMP_ACT_TRAP);
1518 if (ctx == NULL) {
1519 log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
1520 rc = -1;
1521 goto end;
1524 // protectign sandbox parameter strings
1525 if ((rc = prot_strings(ctx, cfg))) {
1526 goto end;
1529 // add parameter filters
1530 if ((rc = add_param_filter(ctx, cfg))) {
1531 log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1532 goto end;
1535 // adding filters with no parameters
1536 if ((rc = add_noparam_filter(ctx))) {
1537 log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1538 goto end;
1541 // loading the seccomp2 filter
1542 if ((rc = seccomp_load(ctx))) {
1543 log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)!", rc,
1544 strerror(-rc));
1545 goto end;
1548 // marking the sandbox as active
1549 sandbox_active = 1;
1551 end:
1552 seccomp_release(ctx);
1553 return (rc < 0 ? -rc : rc);
1556 #include "linux_syscalls.inc"
1557 static const char *
1558 get_syscall_name(int syscall_num)
1560 int i;
1561 for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
1562 if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
1563 return SYSCALLS_BY_NUMBER[i].syscall_name;
1567 static char syscall_name_buf[64];
1568 format_dec_number_sigsafe(syscall_num,
1569 syscall_name_buf, sizeof(syscall_name_buf));
1570 return syscall_name_buf;
1574 #ifdef USE_BACKTRACE
1575 #define MAX_DEPTH 256
1576 static void *syscall_cb_buf[MAX_DEPTH];
1577 #endif
1580 * Function called when a SIGSYS is caught by the application. It notifies the
1581 * user that an error has occurred and either terminates or allows the
1582 * application to continue execution, based on the DEBUGGING_CLOSE symbol.
1584 static void
1585 sigsys_debugging(int nr, siginfo_t *info, void *void_context)
1587 ucontext_t *ctx = (ucontext_t *) (void_context);
1588 const char *syscall_name;
1589 int syscall;
1590 #ifdef USE_BACKTRACE
1591 int depth;
1592 int n_fds, i;
1593 const int *fds = NULL;
1594 #endif
1596 (void) nr;
1598 if (info->si_code != SYS_SECCOMP)
1599 return;
1601 if (!ctx)
1602 return;
1604 syscall = (int) ctx->uc_mcontext.M_SYSCALL;
1606 #ifdef USE_BACKTRACE
1607 depth = backtrace(syscall_cb_buf, MAX_DEPTH);
1608 /* Clean up the top stack frame so we get the real function
1609 * name for the most recently failing function. */
1610 clean_backtrace(syscall_cb_buf, depth, ctx);
1611 #endif
1613 syscall_name = get_syscall_name(syscall);
1615 tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1616 syscall_name,
1617 ")\n",
1618 NULL);
1620 #ifdef USE_BACKTRACE
1621 n_fds = tor_log_get_sigsafe_err_fds(&fds);
1622 for (i=0; i < n_fds; ++i)
1623 backtrace_symbols_fd(syscall_cb_buf, depth, fds[i]);
1624 #endif
1626 #if defined(DEBUGGING_CLOSE)
1627 _exit(1);
1628 #endif // DEBUGGING_CLOSE
1632 * Function that adds a handler for SIGSYS, which is the signal thrown
1633 * when the application is issuing a syscall which is not allowed. The
1634 * main purpose of this function is to help with debugging by identifying
1635 * filtered syscalls.
1637 static int
1638 install_sigsys_debugging(void)
1640 struct sigaction act;
1641 sigset_t mask;
1643 memset(&act, 0, sizeof(act));
1644 sigemptyset(&mask);
1645 sigaddset(&mask, SIGSYS);
1647 act.sa_sigaction = &sigsys_debugging;
1648 act.sa_flags = SA_SIGINFO;
1649 if (sigaction(SIGSYS, &act, NULL) < 0) {
1650 log_err(LD_BUG,"(Sandbox) Failed to register SIGSYS signal handler");
1651 return -1;
1654 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
1655 log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
1656 return -2;
1659 return 0;
1663 * Function responsible of registering the sandbox_cfg_t list of parameter
1664 * syscall filters to the existing parameter list. This is used for incipient
1665 * multiple-sandbox support.
1667 static int
1668 register_cfg(sandbox_cfg_t* cfg)
1670 sandbox_cfg_t *elem = NULL;
1672 if (filter_dynamic == NULL) {
1673 filter_dynamic = cfg;
1674 return 0;
1677 for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
1680 elem->next = cfg;
1682 return 0;
1685 #endif // USE_LIBSECCOMP
1687 #ifdef USE_LIBSECCOMP
1689 * Initialises the syscall sandbox filter for any linux architecture, taking
1690 * into account various available features for different linux flavours.
1692 static int
1693 initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
1695 /* Prevent glibc from trying to open /dev/tty on fatal error */
1696 setenv("LIBC_FATAL_STDERR_", "1", 1);
1698 if (install_sigsys_debugging())
1699 return -1;
1701 if (install_syscall_filter(cfg))
1702 return -2;
1704 if (register_cfg(cfg))
1705 return -3;
1707 return 0;
1711 sandbox_is_active(void)
1713 return sandbox_active != 0;
1715 #endif // USE_LIBSECCOMP
1717 sandbox_cfg_t*
1718 sandbox_cfg_new(void)
1720 return NULL;
1724 sandbox_init(sandbox_cfg_t *cfg)
1726 #if defined(USE_LIBSECCOMP)
1727 return initialise_libseccomp_sandbox(cfg);
1729 #elif defined(__linux__)
1730 (void)cfg;
1731 log_warn(LD_GENERAL,
1732 "This version of Tor was built without support for sandboxing. To "
1733 "build with support for sandboxing on Linux, you must have "
1734 "libseccomp and its necessary header files (e.g. seccomp.h).");
1735 return 0;
1737 #else
1738 (void)cfg;
1739 log_warn(LD_GENERAL,
1740 "Currently, sandboxing is only implemented on Linux. The feature "
1741 "is disabled on your platform.");
1742 return 0;
1743 #endif
1746 #ifndef USE_LIBSECCOMP
1748 sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1750 (void)cfg; (void)file;
1751 return 0;
1755 sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1757 (void)cfg; (void)file;
1758 return 0;
1761 #if 0
1763 sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com)
1765 (void)cfg; (void)com;
1766 return 0;
1768 #endif
1771 sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1773 (void)cfg; (void)file;
1774 return 0;
1778 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1780 (void)cfg; (void)file1; (void)file2;
1781 return 0;
1785 sandbox_is_active(void)
1787 return 0;
1790 void
1791 sandbox_disable_getaddrinfo_cache(void)
1794 #endif