sandbox: refactor string-based option-unchanged tests to use a macro
[tor.git] / src / common / sandbox.c
blobbb2b3ed7427694d4d541c7d75bd24e8c325efdbf
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 */
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 #define DEBUGGING_CLOSE
38 #if defined(USE_LIBSECCOMP)
40 #define _GNU_SOURCE
42 #include <sys/mman.h>
43 #include <sys/syscall.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/epoll.h>
47 #include <sys/prctl.h>
48 #include <linux/futex.h>
49 #include <bits/signum.h>
51 #include <stdarg.h>
52 #include <seccomp.h>
53 #include <signal.h>
54 #include <unistd.h>
55 #include <fcntl.h>
56 #include <time.h>
57 #include <poll.h>
59 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
60 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
61 #define USE_BACKTRACE
62 #define EXPOSE_CLEAN_BACKTRACE
63 #include "backtrace.h"
64 #endif
66 #ifdef USE_BACKTRACE
67 #include <execinfo.h>
68 #endif
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;
77 #undef SCMP_CMP
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[] = {
91 SCMP_SYS(access),
92 SCMP_SYS(brk),
93 SCMP_SYS(clock_gettime),
94 SCMP_SYS(close),
95 SCMP_SYS(clone),
96 SCMP_SYS(epoll_create),
97 SCMP_SYS(epoll_wait),
98 SCMP_SYS(fcntl),
99 SCMP_SYS(fstat),
100 #ifdef __NR_fstat64
101 SCMP_SYS(fstat64),
102 #endif
103 SCMP_SYS(getdents64),
104 SCMP_SYS(getegid),
105 #ifdef __NR_getegid32
106 SCMP_SYS(getegid32),
107 #endif
108 SCMP_SYS(geteuid),
109 #ifdef __NR_geteuid32
110 SCMP_SYS(geteuid32),
111 #endif
112 SCMP_SYS(getgid),
113 #ifdef __NR_getgid32
114 SCMP_SYS(getgid32),
115 #endif
116 SCMP_SYS(getrlimit),
117 SCMP_SYS(gettimeofday),
118 SCMP_SYS(gettid),
119 SCMP_SYS(getuid),
120 #ifdef __NR_getuid32
121 SCMP_SYS(getuid32),
122 #endif
123 SCMP_SYS(lseek),
124 #ifdef __NR__llseek
125 SCMP_SYS(_llseek),
126 #endif
127 SCMP_SYS(mkdir),
128 SCMP_SYS(mlockall),
129 SCMP_SYS(mmap),
130 SCMP_SYS(munmap),
131 SCMP_SYS(read),
132 SCMP_SYS(rt_sigreturn),
133 SCMP_SYS(sched_getaffinity),
134 SCMP_SYS(set_robust_list),
135 #ifdef __NR_sigreturn
136 SCMP_SYS(sigreturn),
137 #endif
138 SCMP_SYS(stat),
139 SCMP_SYS(uname),
140 SCMP_SYS(write),
141 SCMP_SYS(writev),
142 SCMP_SYS(exit_group),
143 SCMP_SYS(exit),
145 SCMP_SYS(madvise),
146 #ifdef __NR_stat64
147 // getaddrinfo uses this..
148 SCMP_SYS(stat64),
149 #endif
152 * These socket syscalls are not required on x86_64 and not supported with
153 * some libseccomp versions (eg: 1.0.1)
155 #if defined(__i386)
156 SCMP_SYS(recv),
157 SCMP_SYS(send),
158 #endif
160 // socket syscalls
161 SCMP_SYS(bind),
162 SCMP_SYS(connect),
163 SCMP_SYS(getsockname),
164 SCMP_SYS(recvmsg),
165 SCMP_SYS(recvfrom),
166 SCMP_SYS(sendto),
167 SCMP_SYS(unlink)
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.
187 static int
188 sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
190 unsigned i;
191 int rc;
192 int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
193 #ifdef SIGXFSZ
194 SIGXFSZ
195 #endif
197 (void) filter;
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]));
202 if (rc)
203 break;
206 return rc;
209 #if 0
211 * Function responsible for setting up the execve syscall for
212 * the seccomp filter sandbox.
214 static int
215 sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
217 int rc;
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));
228 if (rc != 0) {
229 log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received "
230 "libseccomp error %d", rc);
231 return rc;
236 return 0;
238 #endif
241 * Function responsible for setting up the time syscall for
242 * the seccomp filter sandbox.
244 static int
245 sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
247 (void) 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.
256 static int
257 sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
259 int rc = 0;
260 (void)filter;
262 #ifdef __i386__
263 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
264 SCMP_CMP(0, SCMP_CMP_EQ, 18));
265 if (rc) {
266 return rc;
268 #endif
270 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
271 SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
272 if (rc) {
273 return rc;
276 return 0;
279 #ifdef __NR_mmap2
281 * Function responsible for setting up the mmap2 syscall for
282 * the seccomp filter sandbox.
284 static int
285 sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
287 int rc = 0;
288 (void)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));
293 if (rc) {
294 return rc;
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));
300 if (rc) {
301 return rc;
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));
307 if (rc) {
308 return rc;
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));
314 if (rc) {
315 return rc;
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));
321 if (rc) {
322 return rc;
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));
328 if (rc) {
329 return rc;
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));
335 if (rc) {
336 return rc;
339 return 0;
341 #endif
344 * Function responsible for setting up the open syscall for
345 * the seccomp filter sandbox.
347 static int
348 sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
350 int rc;
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
358 == SCMP_SYS(open)) {
359 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
360 SCMP_CMP(0, SCMP_CMP_EQ, param->value));
361 if (rc != 0) {
362 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
363 "libseccomp error %d", rc);
364 return 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));
371 if (rc != 0) {
372 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp "
373 "error %d", rc);
374 return rc;
377 return 0;
380 static int
381 sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
383 int rc;
384 (void) filter;
385 (void) ctx;
387 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl));
388 if (rc != 0) {
389 log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, "
390 "received libseccomp error %d", rc);
391 return rc;
394 return 0;
398 * Function responsible for setting up the rename syscall for
399 * the seccomp filter sandbox.
401 static int
402 sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
404 int rc;
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));
417 if (rc != 0) {
418 log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
419 "libseccomp error %d", rc);
420 return rc;
425 return 0;
429 * Function responsible for setting up the openat syscall for
430 * the seccomp filter sandbox.
432 static int
433 sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
435 int rc;
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|
448 O_CLOEXEC));
449 if (rc != 0) {
450 log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
451 "libseccomp error %d", rc);
452 return rc;
457 return 0;
461 * Function responsible for setting up the socket syscall for
462 * the seccomp filter sandbox.
464 static int
465 sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
467 int rc = 0;
468 int i;
469 (void) filter;
471 #ifdef __i386__
472 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
473 if (rc)
474 return rc;
475 #endif
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));
480 if (rc)
481 return rc;
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));
490 if (rc)
491 return rc;
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));
497 if (rc)
498 return rc;
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));
505 if (rc)
506 return rc;
508 return 0;
512 * Function responsible for setting up the socketpair syscall for
513 * the seccomp filter sandbox.
515 static int
516 sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
518 int rc = 0;
519 (void) filter;
521 #ifdef __i386__
522 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
523 if (rc)
524 return rc;
525 #endif
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));
530 if (rc)
531 return rc;
533 return 0;
537 * Function responsible for setting up the setsockopt syscall for
538 * the seccomp filter sandbox.
540 static int
541 sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
543 int rc = 0;
544 (void) filter;
546 #ifdef __i386__
547 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
548 if (rc)
549 return rc;
550 #endif
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));
555 if (rc)
556 return rc;
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));
562 if (rc)
563 return rc;
564 #endif
566 return 0;
570 * Function responsible for setting up the getsockopt syscall for
571 * the seccomp filter sandbox.
573 static int
574 sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
576 int rc = 0;
577 (void) filter;
579 #ifdef __i386__
580 rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
581 if (rc)
582 return rc;
583 #endif
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));
588 if (rc)
589 return rc;
591 return 0;
594 #ifdef __NR_fcntl64
596 * Function responsible for setting up the fcntl64 syscall for
597 * the seccomp filter sandbox.
599 static int
600 sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
602 int rc = 0;
603 (void) filter;
605 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
606 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
607 if (rc)
608 return rc;
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));
613 if (rc)
614 return rc;
616 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
617 SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
618 if (rc)
619 return rc;
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));
624 if (rc)
625 return rc;
627 return 0;
629 #endif
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..
637 static int
638 sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
640 int rc = 0;
641 (void) 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));
645 if (rc)
646 return rc;
648 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
649 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
650 if (rc)
651 return rc;
653 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
654 SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
655 if (rc)
656 return rc;
658 return 0;
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.
668 static int
669 sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
671 int rc = 0;
672 (void) filter;
674 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
675 SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
676 if (rc)
677 return rc;
679 return 0;
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.
689 static int
690 sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
692 int rc = 0;
693 (void) filter;
695 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
696 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
697 if (rc)
698 return rc;
700 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
701 SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
702 if (rc)
703 return rc;
705 return 0;
709 * Function responsible for setting up the rt_sigprocmask syscall for
710 * the seccomp filter sandbox.
712 static int
713 sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
715 int rc = 0;
716 (void) filter;
718 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
719 SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
720 if (rc)
721 return rc;
723 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
724 SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
725 if (rc)
726 return rc;
728 return 0;
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.
737 static int
738 sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
740 int rc = 0;
741 (void) 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));
745 if (rc)
746 return rc;
748 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
749 SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
750 if (rc)
751 return rc;
753 return 0;
757 * Function responsible for setting up the futex syscall for
758 * the seccomp filter sandbox.
760 static int
761 sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
763 int rc = 0;
764 (void) filter;
766 // can remove
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));
770 if (rc)
771 return rc;
773 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
774 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
775 if (rc)
776 return rc;
778 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
779 SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
780 if (rc)
781 return rc;
783 return 0;
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.
792 static int
793 sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
795 int rc = 0;
796 (void) filter;
798 rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
799 SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
800 if (rc)
801 return rc;
803 return 0;
807 * Function responsible for setting up the poll syscall for
808 * the seccomp filter sandbox.
810 static int
811 sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
813 int rc = 0;
814 (void) 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));
819 if (rc)
820 return rc;
822 return 0;
825 #ifdef __NR_stat64
827 * Function responsible for setting up the stat64 syscall for
828 * the seccomp filter sandbox.
830 static int
831 sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
833 int rc = 0;
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));
844 if (rc != 0) {
845 log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
846 "libseccomp error %d", rc);
847 return rc;
852 return 0;
854 #endif
857 * Array of function pointers responsible for filtering different syscalls at
858 * a parameter level.
860 static sandbox_filter_func_t filter_func[] = {
861 sb_rt_sigaction,
862 sb_rt_sigprocmask,
863 #if 0
864 sb_execve,
865 #endif
866 sb_time,
867 sb_accept4,
868 #ifdef __NR_mmap2
869 sb_mmap2,
870 #endif
871 sb_open,
872 sb_openat,
873 sb__sysctl,
874 sb_rename,
875 #ifdef __NR_fcntl64
876 sb_fcntl64,
877 #endif
878 sb_epoll_ctl,
879 sb_prctl,
880 sb_mprotect,
881 sb_flock,
882 sb_futex,
883 sb_mremap,
884 sb_poll,
885 #ifdef __NR_stat64
886 sb_stat64,
887 #endif
889 sb_socket,
890 sb_setsockopt,
891 sb_getsockopt,
892 sb_socketpair
895 const char *
896 sandbox_intern_string(const char *str)
898 sandbox_cfg_t *elem;
900 if (str == NULL)
901 return NULL;
903 for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
904 smp_param_t *param = elem->param;
906 if (param->prot) {
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;
916 if (sandbox_active)
917 log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
918 return str;
921 /** DOCDOC */
922 static int
923 prot_strings_helper(strmap_t *locations,
924 char **pr_mem_next_p,
925 size_t *pr_mem_left_p,
926 intptr_t *value_p)
928 char *param_val;
929 size_t param_size;
930 void *location;
932 if (*value_p == 0)
933 return 0;
935 param_val = (char*) *value_p;
936 param_size = strlen(param_val) + 1;
937 location = strmap_get(locations, param_val);
939 if (location) {
940 // We already interned this string.
941 tor_free(param_val);
942 *value_p = (intptr_t) location;
943 return 0;
944 } else if (*pr_mem_left_p >= param_size) {
945 // copy to protected
946 location = *pr_mem_next_p;
947 memcpy(location, param_val, param_size);
949 // re-point el parameter to protected
950 tor_free(param_val);
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;
958 return 0;
959 } else {
960 log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
961 return -1;
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
969 * mprotect().
971 static int
972 prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
974 int ret = 0;
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",
992 strerror(errno));
993 ret = -1;
994 goto out;
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) {
1006 ret = -2;
1007 goto out;
1009 if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1010 &el->param->value2) < 0) {
1011 ret = -2;
1012 goto out;
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",
1020 strerror(errno));
1021 ret = -3;
1022 goto out;
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));
1031 if (ret) {
1032 log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
1033 return ret;
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));
1039 if (ret) {
1040 log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
1041 return ret;
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));
1058 if (ret) {
1059 log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
1060 return ret;
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 +
1065 MALLOC_MP_LIM),
1066 SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1067 SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1068 if (ret) {
1069 log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
1070 return ret;
1073 out:
1074 strmap_free(locations, NULL);
1075 return ret;
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
1082 * point.
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;
1095 param->prot = 0;
1097 return elem;
1100 static sandbox_cfg_t*
1101 new_element(int syscall, intptr_t value)
1103 return new_element2(syscall, value, 0);
1106 #ifdef __NR_stat64
1107 #define SCMP_stat SCMP_SYS(stat64)
1108 #else
1109 #define SCMP_stat SCMP_SYS(stat)
1110 #endif
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);
1118 if (!elem) {
1119 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1120 return -1;
1123 elem->next = *cfg;
1124 *cfg = elem;
1126 return 0;
1130 sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...)
1132 int rc = 0;
1133 char *fn = NULL;
1135 va_list ap;
1136 va_start(ap, cfg);
1138 while ((fn = va_arg(ap, char*)) != NULL) {
1139 rc = sandbox_cfg_allow_stat_filename(cfg, fn);
1140 if (rc) {
1141 log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail");
1142 goto end;
1146 end:
1147 va_end(ap);
1148 return 0;
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);
1157 if (!elem) {
1158 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1159 return -1;
1162 elem->next = *cfg;
1163 *cfg = elem;
1165 return 0;
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);
1177 if (!elem) {
1178 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1179 return -1;
1182 elem->next = *cfg;
1183 *cfg = elem;
1185 return 0;
1189 sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...)
1191 int rc = 0;
1192 char *fn = NULL;
1194 va_list ap;
1195 va_start(ap, cfg);
1197 while ((fn = va_arg(ap, char*)) != NULL) {
1198 rc = sandbox_cfg_allow_open_filename(cfg, fn);
1199 if (rc) {
1200 log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_open_filename_array fail");
1201 goto end;
1205 end:
1206 va_end(ap);
1207 return 0;
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);
1216 if (!elem) {
1217 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1218 return -1;
1221 elem->next = *cfg;
1222 *cfg = elem;
1224 return 0;
1228 sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...)
1230 int rc = 0;
1231 char *fn = NULL;
1233 va_list ap;
1234 va_start(ap, cfg);
1236 while ((fn = va_arg(ap, char*)) != NULL) {
1237 rc = sandbox_cfg_allow_openat_filename(cfg, fn);
1238 if (rc) {
1239 log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail");
1240 goto end;
1244 end:
1245 va_end(ap);
1246 return 0;
1249 #if 0
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);
1256 if (!elem) {
1257 log_err(LD_BUG,"(Sandbox) failed to register parameter!");
1258 return -1;
1261 elem->next = *cfg;
1262 *cfg = elem;
1264 return 0;
1268 sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...)
1270 int rc = 0;
1271 char *fn = NULL;
1273 va_list ap;
1274 va_start(ap, cfg);
1276 while ((fn = va_arg(ap, char*)) != NULL) {
1278 rc = sandbox_cfg_allow_execve(cfg, fn);
1279 if (rc) {
1280 log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_execve_array failed");
1281 goto end;
1285 end:
1286 va_end(ap);
1287 return 0;
1289 #endif
1292 sandbox_getaddrinfo(const char *name, const char *servname,
1293 const struct addrinfo *hints,
1294 struct addrinfo **res)
1296 sb_addr_info_t *el;
1298 if (servname != NULL)
1299 return -1;
1301 *res = 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? */
1309 return 0;
1313 if (!sandbox_active) {
1314 if (getaddrinfo(name, NULL, hints, res)) {
1315 log_err(LD_BUG,"(Sandbox) getaddrinfo failed!");
1316 return -1;
1319 return 0;
1322 // getting here means something went wrong
1323 log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
1324 if (*res) {
1325 tor_free(*res);
1326 res = NULL;
1328 return -1;
1332 sandbox_add_addrinfo(const char* name)
1334 int ret;
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));
1345 if (ret) {
1346 log_err(LD_BUG,"(Sandbox) failed to getaddrinfo");
1347 ret = -2;
1348 tor_free(el);
1349 goto out;
1352 el->name = tor_strdup(name);
1353 el->next = sb_addr_info;
1354 sb_addr_info = el;
1356 out:
1357 return ret;
1361 * Function responsible for going through the parameter syscall filters and
1362 * call each function pointer in the list.
1364 static int
1365 add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1367 unsigned i;
1368 int rc = 0;
1370 // function pointer
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 "
1374 "error %d", i, rc);
1375 return rc;
1379 return 0;
1383 * Function responsible of loading the libseccomp syscall filters which do not
1384 * have parameter filtering.
1386 static int
1387 add_noparam_filter(scmp_filter_ctx ctx)
1389 unsigned i;
1390 int rc = 0;
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]);
1395 if (rc != 0) {
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);
1398 return rc;
1402 return 0;
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.
1410 static int
1411 install_syscall_filter(sandbox_cfg_t* cfg)
1413 int rc = 0;
1414 scmp_filter_ctx ctx;
1416 ctx = seccomp_init(SCMP_ACT_TRAP);
1417 if (ctx == NULL) {
1418 log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
1419 rc = -1;
1420 goto end;
1423 // protectign sandbox parameter strings
1424 if ((rc = prot_strings(ctx, cfg))) {
1425 goto end;
1428 // add parameter filters
1429 if ((rc = add_param_filter(ctx, cfg))) {
1430 log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1431 goto end;
1434 // adding filters with no parameters
1435 if ((rc = add_noparam_filter(ctx))) {
1436 log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1437 goto end;
1440 // loading the seccomp2 filter
1441 if ((rc = seccomp_load(ctx))) {
1442 log_err(LD_BUG, "(Sandbox) failed to load!");
1443 goto end;
1446 // marking the sandbox as active
1447 sandbox_active = 1;
1449 end:
1450 seccomp_release(ctx);
1451 return (rc < 0 ? -rc : rc);
1454 #include "linux_syscalls.inc"
1455 static const char *
1456 get_syscall_name(int syscall_num)
1458 int i;
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];
1475 #endif
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.
1482 static void
1483 sigsys_debugging(int nr, siginfo_t *info, void *void_context)
1485 ucontext_t *ctx = (ucontext_t *) (void_context);
1486 const char *syscall_name;
1487 int syscall;
1488 #ifdef USE_BACKTRACE
1489 int depth;
1490 int n_fds, i;
1491 const int *fds = NULL;
1492 #endif
1494 (void) nr;
1496 if (info->si_code != SYS_SECCOMP)
1497 return;
1499 if (!ctx)
1500 return;
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);
1509 #endif
1511 syscall_name = get_syscall_name(syscall);
1513 tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1514 syscall_name,
1515 ")\n",
1516 NULL);
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]);
1522 #endif
1524 #if defined(DEBUGGING_CLOSE)
1525 _exit(1);
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.
1535 static int
1536 install_sigsys_debugging(void)
1538 struct sigaction act;
1539 sigset_t mask;
1541 memset(&act, 0, sizeof(act));
1542 sigemptyset(&mask);
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");
1549 return -1;
1552 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
1553 log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
1554 return -2;
1557 return 0;
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.
1565 static int
1566 register_cfg(sandbox_cfg_t* cfg)
1568 sandbox_cfg_t *elem = NULL;
1570 if (filter_dynamic == NULL) {
1571 filter_dynamic = cfg;
1572 return 0;
1575 for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
1578 elem->next = cfg;
1580 return 0;
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.
1590 static int
1591 initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
1593 if (install_sigsys_debugging())
1594 return -1;
1596 if (install_syscall_filter(cfg))
1597 return -2;
1599 if (register_cfg(cfg))
1600 return -3;
1602 return 0;
1606 sandbox_is_active(void)
1608 return sandbox_active != 0;
1610 #endif // USE_LIBSECCOMP
1612 sandbox_cfg_t*
1613 sandbox_cfg_new(void)
1615 return NULL;
1619 sandbox_init(sandbox_cfg_t *cfg)
1621 #if defined(USE_LIBSECCOMP)
1622 return initialise_libseccomp_sandbox(cfg);
1624 #elif defined(__linux__)
1625 (void)cfg;
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).");
1630 return 0;
1632 #else
1633 (void)cfg;
1634 log_warn(LD_GENERAL,
1635 "Currently, sandboxing is only implemented on Linux. The feature "
1636 "is disabled on your platform.");
1637 return 0;
1638 #endif
1641 #ifndef USE_LIBSECCOMP
1643 sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1645 (void)cfg; (void)file;
1646 return 0;
1650 sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...)
1652 (void)cfg;
1653 return 0;
1657 sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1659 (void)cfg; (void)file;
1660 return 0;
1664 sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...)
1666 (void)cfg;
1667 return 0;
1670 #if 0
1672 sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com)
1674 (void)cfg; (void)com;
1675 return 0;
1679 sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...)
1681 (void)cfg;
1682 return 0;
1684 #endif
1687 sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1689 (void)cfg; (void)file;
1690 return 0;
1694 sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...)
1696 (void)cfg;
1697 return 0;
1701 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1703 (void)cfg; (void)file1; (void)file2;
1704 return 0;
1708 sandbox_is_active(void)
1710 return 0;
1712 #endif