Line data Source code
1 : /* Copyright (c) 2001 Matej Pfajfar.
2 : * Copyright (c) 2001-2004, Roger Dingledine.
3 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 : /* See LICENSE for licensing information */
6 :
7 : /**
8 : * \file sandbox.c
9 : * \brief Code to enable sandboxing.
10 : **/
11 :
12 : #include "orconfig.h"
13 :
14 : #ifndef _LARGEFILE64_SOURCE
15 : /**
16 : * Temporarily required for O_LARGEFILE flag. Needs to be removed
17 : * with the libevent fix.
18 : */
19 : #define _LARGEFILE64_SOURCE
20 : #endif /* !defined(_LARGEFILE64_SOURCE) */
21 :
22 : /** Malloc mprotect limit in bytes.
23 : *
24 : * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
25 : * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
26 : * liblzma have a small overhead that we need to compensate for to avoid being
27 : * killed by the sandbox.
28 : */
29 : #define MALLOC_MP_LIM (20*1024*1024)
30 :
31 : #include <stdio.h>
32 : #include <string.h>
33 : #include <stdlib.h>
34 : #include <errno.h>
35 :
36 : #include "lib/sandbox/sandbox.h"
37 : #include "lib/container/map.h"
38 : #include "lib/err/torerr.h"
39 : #include "lib/log/log.h"
40 : #include "lib/cc/torint.h"
41 : #include "lib/malloc/malloc.h"
42 : #include "lib/string/scanf.h"
43 :
44 : #include "ext/tor_queue.h"
45 : #include "ext/ht.h"
46 : #include "ext/siphash.h"
47 :
48 : #define DEBUGGING_CLOSE
49 :
50 : #if defined(USE_LIBSECCOMP)
51 :
52 : #include <sys/mman.h>
53 : #include <sys/syscall.h>
54 : #include <sys/types.h>
55 : #include <sys/stat.h>
56 : #include <sys/epoll.h>
57 : #include <sys/prctl.h>
58 : #include <linux/futex.h>
59 : #include <sys/file.h>
60 :
61 : #include <stdarg.h>
62 : #include <seccomp.h>
63 : #include <signal.h>
64 : #include <unistd.h>
65 : #include <fcntl.h>
66 : #include <time.h>
67 : #include <poll.h>
68 :
69 : #ifdef HAVE_GNU_LIBC_VERSION_H
70 : #include <gnu/libc-version.h>
71 : #endif
72 : #ifdef HAVE_LINUX_NETFILTER_IPV4_H
73 : #include <linux/netfilter_ipv4.h>
74 : #endif
75 : #ifdef HAVE_LINUX_IF_H
76 : #include <linux/if.h>
77 : #endif
78 : #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
79 : #include <linux/netfilter_ipv6/ip6_tables.h>
80 : #endif
81 :
82 : #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
83 : defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
84 : #define USE_BACKTRACE
85 : #define BACKTRACE_PRIVATE
86 : #include "lib/err/backtrace.h"
87 : #endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
88 :
89 : #ifdef USE_BACKTRACE
90 : #include <execinfo.h>
91 : #endif
92 :
93 : /**
94 : * Linux 32 bit definitions
95 : */
96 : #if defined(__i386__)
97 :
98 : #define REG_SYSCALL REG_EAX
99 : #define M_SYSCALL gregs[REG_SYSCALL]
100 :
101 : /**
102 : * Linux 64 bit definitions
103 : */
104 : #elif defined(__x86_64__)
105 :
106 : #define REG_SYSCALL REG_RAX
107 : #define M_SYSCALL gregs[REG_SYSCALL]
108 :
109 : #elif defined(__arm__)
110 :
111 : #define M_SYSCALL arm_r7
112 :
113 : #elif defined(__aarch64__) && defined(__LP64__)
114 :
115 : #define REG_SYSCALL 8
116 : #define M_SYSCALL regs[REG_SYSCALL]
117 :
118 : #endif /* defined(__i386__) || ... */
119 :
120 : #ifdef M_SYSCALL
121 : #define SYSCALL_NAME_DEBUGGING
122 : #endif
123 :
124 : /**Determines if at least one sandbox is active.*/
125 : static int sandbox_active = 0;
126 : /** Holds the parameter list configuration for the sandbox.*/
127 : static sandbox_cfg_t *filter_dynamic = NULL;
128 :
129 : #undef SCMP_CMP
130 : #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
131 : #define SCMP_CMP_STR(a,b,c) \
132 : ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
133 : #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
134 : /* We use a wrapper here because these masked comparisons seem to be pretty
135 : * verbose. Also, it's important to cast to scmp_datum_t before negating the
136 : * mask, since otherwise the negation might get applied to a 32 bit value, and
137 : * the high bits of the value might get masked out improperly. */
138 : #define SCMP_CMP_MASKED(a,b,c) \
139 : SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
140 : /* For negative constants, the rule to add depends on the glibc version. */
141 : #define SCMP_CMP_NEG(a,op,b) (libc_negative_constant_needs_cast() ? \
142 : (SCMP_CMP((a), (op), (unsigned int)(b))) : \
143 : (SCMP_CMP_STR((a), (op), (b))))
144 :
145 : /** Variable used for storing all syscall numbers that will be allowed with the
146 : * stage 1 general Tor sandbox.
147 : */
148 : static int filter_nopar_gen[] = {
149 : SCMP_SYS(access),
150 : SCMP_SYS(brk),
151 : SCMP_SYS(clock_gettime),
152 : SCMP_SYS(close),
153 : SCMP_SYS(clone),
154 : SCMP_SYS(dup),
155 : SCMP_SYS(epoll_create),
156 : SCMP_SYS(epoll_wait),
157 : #ifdef __NR_epoll_pwait
158 : SCMP_SYS(epoll_pwait),
159 : #endif
160 : #ifdef HAVE_EVENTFD
161 : SCMP_SYS(eventfd2),
162 : #endif
163 : #ifdef HAVE_PIPE2
164 : SCMP_SYS(pipe2),
165 : #endif
166 : #ifdef HAVE_PIPE
167 : SCMP_SYS(pipe),
168 : #endif
169 : #ifdef __NR_fchmod
170 : SCMP_SYS(fchmod),
171 : #endif
172 : SCMP_SYS(fcntl),
173 : SCMP_SYS(fstat),
174 : #ifdef __NR_fstat64
175 : SCMP_SYS(fstat64),
176 : #endif
177 : SCMP_SYS(fsync),
178 : SCMP_SYS(futex),
179 : SCMP_SYS(getdents),
180 : SCMP_SYS(getdents64),
181 : SCMP_SYS(getegid),
182 : #ifdef __NR_getegid32
183 : SCMP_SYS(getegid32),
184 : #endif
185 : SCMP_SYS(geteuid),
186 : #ifdef __NR_geteuid32
187 : SCMP_SYS(geteuid32),
188 : #endif
189 : SCMP_SYS(getgid),
190 : #ifdef __NR_getgid32
191 : SCMP_SYS(getgid32),
192 : #endif
193 : SCMP_SYS(getpid),
194 : #ifdef __NR_getrlimit
195 : SCMP_SYS(getrlimit),
196 : #endif
197 : SCMP_SYS(gettimeofday),
198 : SCMP_SYS(gettid),
199 : SCMP_SYS(getuid),
200 : #ifdef __NR_getuid32
201 : SCMP_SYS(getuid32),
202 : #endif
203 : SCMP_SYS(lseek),
204 : #ifdef __NR__llseek
205 : SCMP_SYS(_llseek),
206 : #endif
207 : // glob uses this..
208 : SCMP_SYS(lstat),
209 : SCMP_SYS(mkdir),
210 : SCMP_SYS(mlockall),
211 : #ifdef __NR_mmap
212 : /* XXXX restrict this in the same ways as mmap2 */
213 : SCMP_SYS(mmap),
214 : #endif
215 : SCMP_SYS(munmap),
216 : #ifdef __NR_nanosleep
217 : SCMP_SYS(nanosleep),
218 : #endif
219 : #ifdef __NR_prlimit
220 : SCMP_SYS(prlimit),
221 : #endif
222 : #ifdef __NR_prlimit64
223 : SCMP_SYS(prlimit64),
224 : #endif
225 : SCMP_SYS(read),
226 : SCMP_SYS(rt_sigreturn),
227 : SCMP_SYS(sched_getaffinity),
228 : #ifdef __NR_sched_yield
229 : SCMP_SYS(sched_yield),
230 : #endif
231 : SCMP_SYS(sendmsg),
232 : SCMP_SYS(set_robust_list),
233 : #ifdef __NR_setrlimit
234 : SCMP_SYS(setrlimit),
235 : #endif
236 : SCMP_SYS(shutdown),
237 : #ifdef __NR_sigaltstack
238 : SCMP_SYS(sigaltstack),
239 : #endif
240 : #ifdef __NR_sigreturn
241 : SCMP_SYS(sigreturn),
242 : #endif
243 : SCMP_SYS(stat),
244 : SCMP_SYS(uname),
245 : SCMP_SYS(wait4),
246 : SCMP_SYS(write),
247 : SCMP_SYS(writev),
248 : SCMP_SYS(exit_group),
249 : SCMP_SYS(exit),
250 :
251 : SCMP_SYS(madvise),
252 : #ifdef __NR_stat64
253 : // getaddrinfo uses this..
254 : SCMP_SYS(stat64),
255 : #endif
256 :
257 : #ifdef __NR_getrandom
258 : SCMP_SYS(getrandom),
259 : #endif
260 :
261 : #ifdef __NR_sysinfo
262 : // qsort uses this..
263 : SCMP_SYS(sysinfo),
264 : #endif
265 : /*
266 : * These socket syscalls are not required on x86_64 and not supported with
267 : * some libseccomp versions (eg: 1.0.1)
268 : */
269 : #if defined(__i386)
270 : SCMP_SYS(recv),
271 : SCMP_SYS(send),
272 : #endif
273 :
274 : // socket syscalls
275 : SCMP_SYS(bind),
276 : SCMP_SYS(listen),
277 : SCMP_SYS(connect),
278 : SCMP_SYS(getsockname),
279 : #ifdef ENABLE_NSS
280 : #ifdef __NR_getpeername
281 : SCMP_SYS(getpeername),
282 : #endif
283 : #endif
284 : SCMP_SYS(recvmsg),
285 : SCMP_SYS(recvfrom),
286 : SCMP_SYS(sendto),
287 : SCMP_SYS(unlink),
288 : #ifdef __NR_unlinkat
289 : SCMP_SYS(unlinkat),
290 : #endif
291 : SCMP_SYS(poll)
292 : };
293 :
294 : /* opendir is not a syscall but it will use either open or openat. We do not
295 : * want the decision to allow open/openat to be the callers reponsability, so
296 : * we create a phony syscall number for opendir and sb_opendir will choose the
297 : * correct syscall. */
298 : #define PHONY_OPENDIR_SYSCALL -2
299 :
300 : /* These macros help avoid the error where the number of filters we add on a
301 : * single rule don't match the arg_cnt param. */
302 : #define seccomp_rule_add_0(ctx,act,call) \
303 : seccomp_rule_add((ctx),(act),(call),0)
304 : #define seccomp_rule_add_1(ctx,act,call,f1) \
305 : seccomp_rule_add((ctx),(act),(call),1,(f1))
306 : #define seccomp_rule_add_2(ctx,act,call,f1,f2) \
307 : seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
308 : #define seccomp_rule_add_3(ctx,act,call,f1,f2,f3) \
309 : seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
310 : #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \
311 : seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
312 :
313 : static const char *sandbox_get_interned_string(const char *str);
314 :
315 : /**
316 : * Function responsible for setting up the rt_sigaction syscall for
317 : * the seccomp filter sandbox.
318 : */
319 : static int
320 0 : sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
321 : {
322 0 : unsigned i;
323 0 : int rc;
324 0 : int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
325 : SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS, SIGIO,
326 : #ifdef SIGXFSZ
327 : SIGXFSZ
328 : #endif
329 : };
330 0 : (void) filter;
331 :
332 0 : for (i = 0; i < ARRAY_LENGTH(param); i++) {
333 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
334 : SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
335 0 : if (rc)
336 : break;
337 : }
338 :
339 0 : return rc;
340 : }
341 :
342 : /**
343 : * Function responsible for setting up the time syscall for
344 : * the seccomp filter sandbox.
345 : */
346 : static int
347 0 : sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
348 : {
349 0 : (void) filter;
350 : #ifdef __NR_time
351 0 : return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
352 : SCMP_CMP(0, SCMP_CMP_EQ, 0));
353 : #else
354 : return 0;
355 : #endif /* defined(__NR_time) */
356 : }
357 :
358 : /**
359 : * Function responsible for setting up the accept4 syscall for
360 : * the seccomp filter sandbox.
361 : */
362 : static int
363 0 : sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
364 : {
365 0 : int rc = 0;
366 0 : (void)filter;
367 :
368 : #ifdef __i386__
369 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
370 : SCMP_CMP(0, SCMP_CMP_EQ, 18));
371 : if (rc) {
372 : return rc;
373 : }
374 : #endif /* defined(__i386__) */
375 :
376 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
377 : SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
378 0 : if (rc) {
379 0 : return rc;
380 : }
381 :
382 : return 0;
383 : }
384 :
385 : #ifdef __NR_mmap2
386 : /**
387 : * Function responsible for setting up the mmap2 syscall for
388 : * the seccomp filter sandbox.
389 : */
390 : static int
391 : sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
392 : {
393 : int rc = 0;
394 : (void)filter;
395 :
396 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
397 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
398 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
399 : if (rc) {
400 : return rc;
401 : }
402 :
403 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
404 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
405 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
406 : if (rc) {
407 : return rc;
408 : }
409 :
410 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
411 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
412 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
413 : if (rc) {
414 : return rc;
415 : }
416 :
417 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
418 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
419 : SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
420 : if (rc) {
421 : return rc;
422 : }
423 :
424 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
425 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
426 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
427 : if (rc) {
428 : return rc;
429 : }
430 :
431 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
432 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
433 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
434 : if (rc) {
435 : return rc;
436 : }
437 :
438 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
439 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
440 : SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
441 : if (rc) {
442 : return rc;
443 : }
444 :
445 : return 0;
446 : }
447 : #endif /* defined(__NR_mmap2) */
448 :
449 : #ifdef HAVE_GNU_LIBC_VERSION_H
450 : #ifdef HAVE_GNU_GET_LIBC_VERSION
451 : #define CHECK_LIBC_VERSION
452 : #endif
453 : #endif
454 :
455 : /* Return true the libc version is greater or equal than
456 : * <b>major</b>.<b>minor</b>. Returns false otherwise. */
457 : static int
458 0 : is_libc_at_least(int major, int minor)
459 : {
460 : #ifdef CHECK_LIBC_VERSION
461 0 : const char *version = gnu_get_libc_version();
462 0 : if (version == NULL)
463 : return 0;
464 :
465 0 : int libc_major = -1;
466 0 : int libc_minor = -1;
467 :
468 0 : tor_sscanf(version, "%d.%d", &libc_major, &libc_minor);
469 0 : if (libc_major > major)
470 : return 1;
471 0 : else if (libc_major == major && libc_minor >= minor)
472 : return 1;
473 : else
474 0 : return 0;
475 : #else /* !defined(CHECK_LIBC_VERSION) */
476 : (void)major;
477 : (void)minor;
478 : return 0;
479 : #endif /* defined(CHECK_LIBC_VERSION) */
480 : }
481 :
482 : /* Return true if we think we're running with a libc that uses openat for the
483 : * open function on linux. */
484 : static int
485 0 : libc_uses_openat_for_open(void)
486 : {
487 0 : return is_libc_at_least(2, 26);
488 : }
489 :
490 : /* Return true if we think we're running with a libc that uses openat for the
491 : * opendir function on linux. */
492 : static int
493 0 : libc_uses_openat_for_opendir(void)
494 : {
495 : // libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
496 0 : return is_libc_at_least(2, 27) ||
497 0 : (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
498 : }
499 :
500 : /* Return true if we think we're running with a libc that needs to cast
501 : * negative arguments like AT_FDCWD for seccomp rules. */
502 : static int
503 0 : libc_negative_constant_needs_cast(void)
504 : {
505 0 : return is_libc_at_least(2, 27);
506 : }
507 :
508 : /** Allow a single file to be opened. If <b>use_openat</b> is true,
509 : * we're using a libc that remaps all the opens into openats. */
510 : static int
511 0 : allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
512 : {
513 0 : if (use_openat) {
514 0 : return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
515 : SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
516 : SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
517 : } else {
518 0 : return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
519 : SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
520 : }
521 : }
522 :
523 : /**
524 : * Function responsible for setting up the open syscall for
525 : * the seccomp filter sandbox.
526 : */
527 : static int
528 0 : sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
529 : {
530 0 : int rc;
531 0 : sandbox_cfg_t *elem = NULL;
532 :
533 0 : int use_openat = libc_uses_openat_for_open();
534 :
535 : // for each dynamic parameter filters
536 0 : for (elem = filter; elem != NULL; elem = elem->next) {
537 0 : smp_param_t *param = elem->param;
538 :
539 0 : if (param != NULL && param->prot == 1 && param->syscall
540 : == SCMP_SYS(open)) {
541 0 : rc = allow_file_open(ctx, use_openat, param->value);
542 0 : if (rc != 0) {
543 0 : log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
544 : "libseccomp error %d", rc);
545 0 : return rc;
546 : }
547 : }
548 : }
549 :
550 : return 0;
551 : }
552 :
553 : static int
554 0 : sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
555 : {
556 0 : int rc;
557 0 : sandbox_cfg_t *elem = NULL;
558 :
559 : // for each dynamic parameter filters
560 0 : for (elem = filter; elem != NULL; elem = elem->next) {
561 0 : smp_param_t *param = elem->param;
562 :
563 0 : if (param != NULL && param->prot == 1 && param->syscall
564 : == SCMP_SYS(chmod)) {
565 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
566 : SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
567 0 : if (rc != 0) {
568 0 : log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
569 : "libseccomp error %d", rc);
570 0 : return rc;
571 : }
572 : }
573 : }
574 :
575 : return 0;
576 : }
577 :
578 : static int
579 0 : sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
580 : {
581 0 : int rc;
582 0 : sandbox_cfg_t *elem = NULL;
583 :
584 : // for each dynamic parameter filters
585 0 : for (elem = filter; elem != NULL; elem = elem->next) {
586 0 : smp_param_t *param = elem->param;
587 :
588 0 : if (param != NULL && param->prot == 1 && param->syscall
589 : == SCMP_SYS(chown)) {
590 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
591 : SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
592 0 : if (rc != 0) {
593 0 : log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
594 : "libseccomp error %d", rc);
595 0 : return rc;
596 : }
597 : }
598 : }
599 :
600 : return 0;
601 : }
602 :
603 : /**
604 : * Function responsible for setting up the rename syscall for
605 : * the seccomp filter sandbox.
606 : */
607 : static int
608 0 : sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
609 : {
610 0 : int rc;
611 0 : sandbox_cfg_t *elem = NULL;
612 :
613 : // for each dynamic parameter filters
614 0 : for (elem = filter; elem != NULL; elem = elem->next) {
615 0 : smp_param_t *param = elem->param;
616 :
617 0 : if (param != NULL && param->prot == 1 &&
618 0 : param->syscall == SCMP_SYS(rename)) {
619 :
620 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
621 : SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
622 : SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
623 0 : if (rc != 0) {
624 0 : log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
625 : "libseccomp error %d", rc);
626 0 : return rc;
627 : }
628 : }
629 : }
630 :
631 : return 0;
632 : }
633 :
634 : /**
635 : * Function responsible for setting up the openat syscall for
636 : * the seccomp filter sandbox.
637 : */
638 : static int
639 0 : sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
640 : {
641 0 : int rc;
642 0 : sandbox_cfg_t *elem = NULL;
643 :
644 : // for each dynamic parameter filters
645 0 : for (elem = filter; elem != NULL; elem = elem->next) {
646 0 : smp_param_t *param = elem->param;
647 :
648 0 : if (param != NULL && param->prot == 1 && param->syscall
649 : == SCMP_SYS(openat)) {
650 0 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
651 : SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
652 : SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
653 : SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
654 : O_CLOEXEC));
655 0 : if (rc != 0) {
656 0 : log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
657 : "libseccomp error %d", rc);
658 0 : return rc;
659 : }
660 : }
661 : }
662 :
663 : return 0;
664 : }
665 :
666 : static int
667 0 : sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
668 : {
669 0 : int rc;
670 0 : sandbox_cfg_t *elem = NULL;
671 :
672 : // for each dynamic parameter filters
673 0 : for (elem = filter; elem != NULL; elem = elem->next) {
674 0 : smp_param_t *param = elem->param;
675 :
676 0 : if (param != NULL && param->prot == 1 && param->syscall
677 : == PHONY_OPENDIR_SYSCALL) {
678 0 : rc = allow_file_open(ctx, libc_uses_openat_for_opendir(), param->value);
679 0 : if (rc != 0) {
680 0 : log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
681 : "libseccomp error %d", rc);
682 0 : return rc;
683 : }
684 : }
685 : }
686 :
687 : return 0;
688 : }
689 :
690 : /**
691 : * Function responsible for setting up the socket syscall for
692 : * the seccomp filter sandbox.
693 : */
694 : static int
695 0 : sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
696 : {
697 0 : int rc = 0;
698 0 : int i, j;
699 0 : (void) filter;
700 :
701 : #ifdef __i386__
702 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
703 : if (rc)
704 : return rc;
705 : #endif
706 :
707 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
708 : SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
709 : SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
710 0 : if (rc)
711 : return rc;
712 :
713 0 : for (i = 0; i < 2; ++i) {
714 0 : const int pf = i ? PF_INET : PF_INET6;
715 0 : for (j=0; j < 3; ++j) {
716 0 : const int type = (j == 0) ? SOCK_STREAM :
717 : SOCK_DGRAM;
718 0 : const int protocol = (j == 0) ? IPPROTO_TCP :
719 0 : (j == 1) ? IPPROTO_IP :
720 : IPPROTO_UDP;
721 0 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
722 : SCMP_CMP(0, SCMP_CMP_EQ, pf),
723 : SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
724 : SCMP_CMP(2, SCMP_CMP_EQ, protocol));
725 0 : if (rc)
726 0 : return rc;
727 : }
728 : }
729 :
730 : #ifdef ENABLE_NSS
731 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
732 : SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
733 : SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
734 : SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
735 : if (rc)
736 : return rc;
737 : #endif /* defined(ENABLE_NSS) */
738 :
739 0 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
740 : SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
741 : SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
742 : SCMP_CMP(2, SCMP_CMP_EQ, 0));
743 0 : if (rc)
744 : return rc;
745 :
746 0 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
747 : SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
748 : SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
749 : SCMP_CMP(2, SCMP_CMP_EQ, 0));
750 0 : if (rc)
751 : return rc;
752 :
753 0 : rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
754 : SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
755 : SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
756 : SCMP_CMP(2, SCMP_CMP_EQ, 0));
757 0 : if (rc)
758 0 : return rc;
759 :
760 : return 0;
761 : }
762 :
763 : /**
764 : * Function responsible for setting up the socketpair syscall for
765 : * the seccomp filter sandbox.
766 : */
767 : static int
768 0 : sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
769 : {
770 0 : int rc = 0;
771 0 : (void) filter;
772 :
773 : #ifdef __i386__
774 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
775 : if (rc)
776 : return rc;
777 : #endif
778 :
779 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
780 : SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
781 : SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
782 0 : if (rc)
783 0 : return rc;
784 :
785 : return 0;
786 : }
787 :
788 : #ifdef HAVE_KIST_SUPPORT
789 :
790 : #include <linux/sockios.h>
791 :
792 : static int
793 0 : sb_ioctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
794 : {
795 0 : int rc;
796 0 : (void) filter;
797 :
798 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
799 : SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
800 0 : if (rc)
801 0 : return rc;
802 : return 0;
803 : }
804 :
805 : #endif /* defined(HAVE_KIST_SUPPORT) */
806 :
807 : /**
808 : * Function responsible for setting up the setsockopt syscall for
809 : * the seccomp filter sandbox.
810 : */
811 : static int
812 0 : sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
813 : {
814 0 : int rc = 0;
815 0 : (void) filter;
816 :
817 : #ifdef __i386__
818 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
819 : if (rc)
820 : return rc;
821 : #endif
822 :
823 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
824 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
825 : SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
826 0 : if (rc)
827 : return rc;
828 :
829 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
830 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
831 : SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
832 0 : if (rc)
833 : return rc;
834 :
835 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
836 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
837 : SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
838 0 : if (rc)
839 : return rc;
840 :
841 : #ifdef HAVE_SYSTEMD
842 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
843 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
844 : SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
845 0 : if (rc)
846 : return rc;
847 : #endif /* defined(HAVE_SYSTEMD) */
848 :
849 : #ifdef IP_TRANSPARENT
850 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
851 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
852 : SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
853 0 : if (rc)
854 : return rc;
855 : #endif /* defined(IP_TRANSPARENT) */
856 :
857 : #ifdef IPV6_V6ONLY
858 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
859 : SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
860 : SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
861 0 : if (rc)
862 0 : return rc;
863 : #endif /* defined(IPV6_V6ONLY) */
864 :
865 : return 0;
866 : }
867 :
868 : /**
869 : * Function responsible for setting up the getsockopt syscall for
870 : * the seccomp filter sandbox.
871 : */
872 : static int
873 0 : sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
874 : {
875 0 : int rc = 0;
876 0 : (void) filter;
877 :
878 : #ifdef __i386__
879 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
880 : if (rc)
881 : return rc;
882 : #endif
883 :
884 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
885 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
886 : SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
887 0 : if (rc)
888 : return rc;
889 :
890 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
891 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
892 : SCMP_CMP(2, SCMP_CMP_EQ, SO_ACCEPTCONN));
893 0 : if (rc)
894 : return rc;
895 :
896 : #ifdef HAVE_SYSTEMD
897 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
898 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
899 : SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
900 0 : if (rc)
901 : return rc;
902 : #endif /* defined(HAVE_SYSTEMD) */
903 :
904 : #ifdef HAVE_LINUX_NETFILTER_IPV4_H
905 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
906 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
907 : SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
908 0 : if (rc)
909 : return rc;
910 : #endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
911 :
912 : #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
913 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
914 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
915 : SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
916 0 : if (rc)
917 : return rc;
918 : #endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
919 :
920 : #ifdef HAVE_KIST_SUPPORT
921 : #include <netinet/tcp.h>
922 0 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
923 : SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
924 : SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
925 0 : if (rc)
926 0 : return rc;
927 : #endif /* defined(HAVE_KIST_SUPPORT) */
928 :
929 : return 0;
930 : }
931 :
932 : #ifdef __NR_fcntl64
933 : /**
934 : * Function responsible for setting up the fcntl64 syscall for
935 : * the seccomp filter sandbox.
936 : */
937 : static int
938 : sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
939 : {
940 : int rc = 0;
941 : (void) filter;
942 :
943 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
944 : SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
945 : if (rc)
946 : return rc;
947 :
948 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
949 : SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
950 : SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
951 : if (rc)
952 : return rc;
953 :
954 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
955 : SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
956 : if (rc)
957 : return rc;
958 :
959 : rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
960 : SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
961 : SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
962 : if (rc)
963 : return rc;
964 :
965 : return 0;
966 : }
967 : #endif /* defined(__NR_fcntl64) */
968 :
969 : /**
970 : * Function responsible for setting up the epoll_ctl syscall for
971 : * the seccomp filter sandbox.
972 : *
973 : * Note: basically allows everything but will keep for now..
974 : */
975 : static int
976 0 : sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
977 : {
978 0 : int rc = 0;
979 0 : (void) filter;
980 :
981 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
982 : SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
983 0 : if (rc)
984 : return rc;
985 :
986 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
987 : SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
988 0 : if (rc)
989 : return rc;
990 :
991 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
992 : SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
993 0 : if (rc)
994 0 : return rc;
995 :
996 : return 0;
997 : }
998 :
999 : /**
1000 : * Function responsible for setting up the prctl syscall for
1001 : * the seccomp filter sandbox.
1002 : *
1003 : * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
1004 : * to be allowlisted in this function.
1005 : */
1006 : static int
1007 0 : sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1008 : {
1009 0 : int rc = 0;
1010 0 : (void) filter;
1011 :
1012 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1013 : SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
1014 0 : if (rc)
1015 0 : return rc;
1016 :
1017 : return 0;
1018 : }
1019 :
1020 : /**
1021 : * Function responsible for setting up the mprotect syscall for
1022 : * the seccomp filter sandbox.
1023 : *
1024 : * NOTE: does not NEED to be here.. currently only occurs before filter; will
1025 : * keep just in case for the future.
1026 : */
1027 : static int
1028 0 : sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1029 : {
1030 0 : int rc = 0;
1031 0 : (void) filter;
1032 :
1033 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1034 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
1035 0 : if (rc)
1036 : return rc;
1037 :
1038 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1039 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
1040 0 : if (rc)
1041 0 : return rc;
1042 :
1043 : return 0;
1044 : }
1045 :
1046 : /**
1047 : * Function responsible for setting up the rt_sigprocmask syscall for
1048 : * the seccomp filter sandbox.
1049 : */
1050 : static int
1051 0 : sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1052 : {
1053 0 : int rc = 0;
1054 0 : (void) filter;
1055 :
1056 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1057 : SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
1058 0 : if (rc)
1059 : return rc;
1060 :
1061 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1062 : SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
1063 0 : if (rc)
1064 0 : return rc;
1065 :
1066 : return 0;
1067 : }
1068 :
1069 : /**
1070 : * Function responsible for setting up the flock syscall for
1071 : * the seccomp filter sandbox.
1072 : *
1073 : * NOTE: does not need to be here, occurs before filter is applied.
1074 : */
1075 : static int
1076 0 : sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1077 : {
1078 0 : int rc = 0;
1079 0 : (void) filter;
1080 :
1081 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1082 : SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
1083 0 : if (rc)
1084 : return rc;
1085 :
1086 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1087 : SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
1088 0 : if (rc)
1089 0 : return rc;
1090 :
1091 : return 0;
1092 : }
1093 :
1094 : /**
1095 : * Function responsible for setting up the futex syscall for
1096 : * the seccomp filter sandbox.
1097 : */
1098 : static int
1099 0 : sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1100 : {
1101 0 : int rc = 0;
1102 0 : (void) filter;
1103 :
1104 : // can remove
1105 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1106 : SCMP_CMP(1, SCMP_CMP_EQ,
1107 : FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
1108 0 : if (rc)
1109 : return rc;
1110 :
1111 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1112 : SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
1113 0 : if (rc)
1114 : return rc;
1115 :
1116 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1117 : SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
1118 0 : if (rc)
1119 0 : return rc;
1120 :
1121 : return 0;
1122 : }
1123 :
1124 : /**
1125 : * Function responsible for setting up the mremap syscall for
1126 : * the seccomp filter sandbox.
1127 : *
1128 : * NOTE: so far only occurs before filter is applied.
1129 : */
1130 : static int
1131 0 : sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1132 : {
1133 0 : int rc = 0;
1134 0 : (void) filter;
1135 :
1136 0 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
1137 : SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
1138 0 : if (rc)
1139 0 : return rc;
1140 :
1141 : return 0;
1142 : }
1143 :
1144 : #ifdef __NR_stat64
1145 : /**
1146 : * Function responsible for setting up the stat64 syscall for
1147 : * the seccomp filter sandbox.
1148 : */
1149 : static int
1150 : sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1151 : {
1152 : int rc = 0;
1153 : sandbox_cfg_t *elem = NULL;
1154 :
1155 : // for each dynamic parameter filters
1156 : for (elem = filter; elem != NULL; elem = elem->next) {
1157 : smp_param_t *param = elem->param;
1158 :
1159 : if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1160 : || param->syscall == SCMP_SYS(stat64))) {
1161 : rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
1162 : SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
1163 : if (rc != 0) {
1164 : log_err(LD_BUG,"(Sandbox) failed to add stat64 syscall, received "
1165 : "libseccomp error %d", rc);
1166 : return rc;
1167 : }
1168 : }
1169 : }
1170 :
1171 : return 0;
1172 : }
1173 : #endif /* defined(__NR_stat64) */
1174 :
1175 : static int
1176 0 : sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1177 : {
1178 0 : (void) filter;
1179 : #ifdef __NR_kill
1180 : /* Allow killing anything with signal 0 -- it isn't really a kill. */
1181 0 : return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill),
1182 : SCMP_CMP(1, SCMP_CMP_EQ, 0));
1183 : #else
1184 : return 0;
1185 : #endif /* defined(__NR_kill) */
1186 : }
1187 :
1188 : /**
1189 : * Array of function pointers responsible for filtering different syscalls at
1190 : * a parameter level.
1191 : */
1192 : static sandbox_filter_func_t filter_func[] = {
1193 : sb_rt_sigaction,
1194 : sb_rt_sigprocmask,
1195 : sb_time,
1196 : sb_accept4,
1197 : #ifdef __NR_mmap2
1198 : sb_mmap2,
1199 : #endif
1200 : sb_chown,
1201 : sb_chmod,
1202 : sb_open,
1203 : sb_openat,
1204 : sb_opendir,
1205 : sb_rename,
1206 : #ifdef __NR_fcntl64
1207 : sb_fcntl64,
1208 : #endif
1209 : sb_epoll_ctl,
1210 : sb_prctl,
1211 : sb_mprotect,
1212 : sb_flock,
1213 : sb_futex,
1214 : sb_mremap,
1215 : #ifdef __NR_stat64
1216 : sb_stat64,
1217 : #endif
1218 :
1219 : sb_socket,
1220 : sb_setsockopt,
1221 : sb_getsockopt,
1222 : sb_socketpair,
1223 : #ifdef HAVE_KIST_SUPPORT
1224 : sb_ioctl,
1225 : #endif
1226 : sb_kill
1227 : };
1228 :
1229 : /**
1230 : * Return the interned (and hopefully sandbox-permitted) string equal
1231 : * to @a str.
1232 : *
1233 : * Return NULL if `str` is NULL, or `str` is not an interned string.
1234 : **/
1235 : const char *
1236 7287 : sandbox_intern_string(const char *str)
1237 : {
1238 7287 : const char *interned = sandbox_get_interned_string(str);
1239 :
1240 7287 : if (sandbox_active && str != NULL && interned == NULL) {
1241 0 : log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
1242 : }
1243 :
1244 7287 : return interned ? interned : str;
1245 : }
1246 :
1247 : /**
1248 : * Return true if the sandbox is running and we are missing an interned string
1249 : * equal to @a str.
1250 : */
1251 : bool
1252 306 : sandbox_interned_string_is_missing(const char *str)
1253 : {
1254 306 : return sandbox_active && sandbox_get_interned_string(str) == NULL;
1255 : }
1256 :
1257 : /**
1258 : * Try to find and return the interned string equal to @a str.
1259 : *
1260 : * If there is no such string, return NULL.
1261 : **/
1262 : static const char *
1263 7287 : sandbox_get_interned_string(const char *str)
1264 : {
1265 7287 : sandbox_cfg_t *elem;
1266 :
1267 7287 : if (str == NULL)
1268 : return NULL;
1269 :
1270 7287 : for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
1271 0 : smp_param_t *param = elem->param;
1272 :
1273 0 : if (param->prot) {
1274 0 : if (!strcmp(str, (char*)(param->value))) {
1275 0 : return (char*)param->value;
1276 : }
1277 0 : if (param->value2 && !strcmp(str, (char*)param->value2)) {
1278 0 : return (char*)param->value2;
1279 : }
1280 : }
1281 : }
1282 :
1283 : return NULL;
1284 : }
1285 :
1286 : /* DOCDOC */
1287 : static int
1288 0 : prot_strings_helper(strmap_t *locations,
1289 : char **pr_mem_next_p,
1290 : size_t *pr_mem_left_p,
1291 : char **value_p)
1292 : {
1293 0 : char *param_val;
1294 0 : size_t param_size;
1295 0 : void *location;
1296 :
1297 0 : if (*value_p == 0)
1298 : return 0;
1299 :
1300 0 : param_val = (char*) *value_p;
1301 0 : param_size = strlen(param_val) + 1;
1302 0 : location = strmap_get(locations, param_val);
1303 :
1304 0 : if (location) {
1305 : // We already interned this string.
1306 0 : tor_free(param_val);
1307 0 : *value_p = location;
1308 0 : return 0;
1309 0 : } else if (*pr_mem_left_p >= param_size) {
1310 : // copy to protected
1311 0 : location = *pr_mem_next_p;
1312 0 : memcpy(location, param_val, param_size);
1313 :
1314 : // re-point el parameter to protected
1315 0 : tor_free(param_val);
1316 0 : *value_p = location;
1317 :
1318 0 : strmap_set(locations, location, location); /* good real estate advice */
1319 :
1320 : // move next available protected memory
1321 0 : *pr_mem_next_p += param_size;
1322 0 : *pr_mem_left_p -= param_size;
1323 0 : return 0;
1324 : } else {
1325 0 : log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
1326 0 : return -1;
1327 : }
1328 : }
1329 :
1330 : /**
1331 : * Protects all the strings in the sandbox's parameter list configuration. It
1332 : * works by calculating the total amount of memory required by the parameter
1333 : * list, allocating the memory using mmap, and protecting it from writes with
1334 : * mprotect().
1335 : */
1336 : static int
1337 0 : prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1338 : {
1339 0 : int ret = 0;
1340 0 : size_t pr_mem_size = 0, pr_mem_left = 0;
1341 0 : char *pr_mem_next = NULL, *pr_mem_base;
1342 0 : sandbox_cfg_t *el = NULL;
1343 0 : strmap_t *locations = NULL;
1344 :
1345 : // get total number of bytes required to mmap. (Overestimate.)
1346 0 : for (el = cfg; el != NULL; el = el->next) {
1347 0 : pr_mem_size += strlen((char*) el->param->value) + 1;
1348 0 : if (el->param->value2)
1349 0 : pr_mem_size += strlen((char*) el->param->value2) + 1;
1350 : }
1351 :
1352 : // allocate protected memory with MALLOC_MP_LIM canary
1353 0 : pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
1354 : PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1355 0 : if (pr_mem_base == MAP_FAILED) {
1356 0 : log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
1357 : strerror(errno));
1358 0 : ret = -1;
1359 0 : goto out;
1360 : }
1361 :
1362 0 : pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
1363 0 : pr_mem_left = pr_mem_size;
1364 :
1365 0 : locations = strmap_new();
1366 :
1367 : // change el value pointer to protected
1368 0 : for (el = cfg; el != NULL; el = el->next) {
1369 0 : if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1370 0 : &el->param->value) < 0) {
1371 0 : ret = -2;
1372 0 : goto out;
1373 : }
1374 0 : if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1375 0 : &el->param->value2) < 0) {
1376 0 : ret = -2;
1377 0 : goto out;
1378 : }
1379 0 : el->param->prot = 1;
1380 : }
1381 :
1382 : // protecting from writes
1383 0 : if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1384 0 : log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
1385 : strerror(errno));
1386 0 : ret = -3;
1387 0 : goto out;
1388 : }
1389 :
1390 : /*
1391 : * Setting sandbox restrictions so the string memory cannot be tampered with
1392 : */
1393 : // no mremap of the protected base address
1394 0 : ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
1395 : SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1396 0 : if (ret) {
1397 0 : log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
1398 0 : goto out;
1399 : }
1400 :
1401 : // no munmap of the protected base address
1402 0 : ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
1403 : SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1404 0 : if (ret) {
1405 0 : log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
1406 0 : goto out;
1407 : }
1408 :
1409 : /*
1410 : * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
1411 : * never over the memory region used by the protected strings.
1412 : *
1413 : * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
1414 : * had to be removed due to limitation of libseccomp regarding intervals.
1415 : *
1416 : * There is a restriction on how much you can mprotect with R|W up to the
1417 : * size of the canary.
1418 : */
1419 0 : ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1420 : SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
1421 : SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1422 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1423 0 : if (ret) {
1424 0 : log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
1425 0 : goto out;
1426 : }
1427 :
1428 0 : ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1429 : SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
1430 : MALLOC_MP_LIM),
1431 : SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1432 : SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1433 0 : if (ret) {
1434 0 : log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
1435 0 : goto out;
1436 : }
1437 :
1438 0 : out:
1439 0 : strmap_free(locations, NULL);
1440 0 : return ret;
1441 : }
1442 :
1443 : /**
1444 : * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
1445 : * its values according the parameter list. All elements are initialised
1446 : * with the 'prot' field set to false, as the pointer is not protected at this
1447 : * point.
1448 : */
1449 : static sandbox_cfg_t*
1450 0 : new_element2(int syscall, char *value, char *value2)
1451 : {
1452 0 : smp_param_t *param = NULL;
1453 :
1454 0 : sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
1455 0 : param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
1456 :
1457 0 : param->syscall = syscall;
1458 0 : param->value = value;
1459 0 : param->value2 = value2;
1460 0 : param->prot = 0;
1461 :
1462 0 : return elem;
1463 : }
1464 :
1465 : static sandbox_cfg_t*
1466 0 : new_element(int syscall, char *value)
1467 : {
1468 0 : return new_element2(syscall, value, NULL);
1469 : }
1470 :
1471 : #ifdef __NR_stat64
1472 : #define SCMP_stat SCMP_SYS(stat64)
1473 : #else
1474 : #define SCMP_stat SCMP_SYS(stat)
1475 : #endif
1476 :
1477 : int
1478 0 : sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1479 : {
1480 0 : sandbox_cfg_t *elem = NULL;
1481 :
1482 0 : elem = new_element(SCMP_stat, file);
1483 :
1484 0 : elem->next = *cfg;
1485 0 : *cfg = elem;
1486 :
1487 0 : return 0;
1488 : }
1489 :
1490 : int
1491 0 : sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1492 : {
1493 0 : sandbox_cfg_t *elem = NULL;
1494 :
1495 0 : elem = new_element(SCMP_SYS(open), file);
1496 :
1497 0 : elem->next = *cfg;
1498 0 : *cfg = elem;
1499 :
1500 0 : return 0;
1501 : }
1502 :
1503 : int
1504 0 : sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
1505 : {
1506 0 : sandbox_cfg_t *elem = NULL;
1507 :
1508 0 : elem = new_element(SCMP_SYS(chmod), file);
1509 :
1510 0 : elem->next = *cfg;
1511 0 : *cfg = elem;
1512 :
1513 0 : return 0;
1514 : }
1515 :
1516 : int
1517 0 : sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
1518 : {
1519 0 : sandbox_cfg_t *elem = NULL;
1520 :
1521 0 : elem = new_element(SCMP_SYS(chown), file);
1522 :
1523 0 : elem->next = *cfg;
1524 0 : *cfg = elem;
1525 :
1526 0 : return 0;
1527 : }
1528 :
1529 : int
1530 0 : sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1531 : {
1532 0 : sandbox_cfg_t *elem = NULL;
1533 :
1534 0 : elem = new_element2(SCMP_SYS(rename), file1, file2);
1535 :
1536 0 : elem->next = *cfg;
1537 0 : *cfg = elem;
1538 :
1539 0 : return 0;
1540 : }
1541 :
1542 : int
1543 0 : sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1544 : {
1545 0 : sandbox_cfg_t *elem = NULL;
1546 :
1547 0 : elem = new_element(SCMP_SYS(openat), file);
1548 :
1549 0 : elem->next = *cfg;
1550 0 : *cfg = elem;
1551 :
1552 0 : return 0;
1553 : }
1554 :
1555 : int
1556 0 : sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
1557 : {
1558 0 : sandbox_cfg_t *elem = NULL;
1559 :
1560 0 : elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
1561 :
1562 0 : elem->next = *cfg;
1563 0 : *cfg = elem;
1564 :
1565 0 : return 0;
1566 : }
1567 :
1568 : /**
1569 : * Function responsible for going through the parameter syscall filters and
1570 : * call each function pointer in the list.
1571 : */
1572 : static int
1573 0 : add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1574 : {
1575 0 : unsigned i;
1576 0 : int rc = 0;
1577 :
1578 : // function pointer
1579 0 : for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
1580 0 : rc = filter_func[i](ctx, cfg);
1581 0 : if (rc) {
1582 0 : log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
1583 : "error %d", i, rc);
1584 0 : return rc;
1585 : }
1586 : }
1587 :
1588 : return 0;
1589 : }
1590 :
1591 : /**
1592 : * Function responsible of loading the libseccomp syscall filters which do not
1593 : * have parameter filtering.
1594 : */
1595 : static int
1596 0 : add_noparam_filter(scmp_filter_ctx ctx)
1597 : {
1598 0 : unsigned i;
1599 0 : int rc = 0;
1600 :
1601 : // add general filters
1602 0 : for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
1603 0 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
1604 0 : if (rc != 0) {
1605 0 : log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), "
1606 : "received libseccomp error %d", i, filter_nopar_gen[i], rc);
1607 0 : return rc;
1608 : }
1609 : }
1610 :
1611 0 : if (is_libc_at_least(2, 33)) {
1612 : #ifdef __NR_newfstatat
1613 : // Libc 2.33 uses this syscall to implement both fstat() and stat().
1614 : //
1615 : // The trouble is that to implement fstat(fd, &st), it calls:
1616 : // newfstatat(fs, "", &st, AT_EMPTY_PATH)
1617 : // We can't detect this usage in particular, because "" is a pointer
1618 : // we don't control. And we can't just look for AT_EMPTY_PATH, since
1619 : // AT_EMPTY_PATH only has effect when the path string is empty.
1620 : //
1621 : // So our only solution seems to be allowing all fstatat calls, which
1622 : // means that an attacker can stat() anything on the filesystem. That's
1623 : // not a great solution, but I can't find a better one.
1624 0 : rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat));
1625 0 : if (rc != 0) {
1626 0 : log_err(LD_BUG,"(Sandbox) failed to add newfstatat() syscall; "
1627 : "received libseccomp error %d", rc);
1628 0 : return rc;
1629 : }
1630 : #endif
1631 : }
1632 :
1633 : return 0;
1634 : }
1635 :
1636 : /**
1637 : * Function responsible for setting up and enabling a global syscall filter.
1638 : * The function is a prototype developed for stage 1 of sandboxing Tor.
1639 : * Returns 0 on success.
1640 : */
1641 : static int
1642 0 : install_syscall_filter(sandbox_cfg_t* cfg)
1643 : {
1644 0 : int rc = 0;
1645 0 : scmp_filter_ctx ctx;
1646 :
1647 0 : ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
1648 0 : if (ctx == NULL) {
1649 0 : log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
1650 0 : rc = -1;
1651 0 : goto end;
1652 : }
1653 :
1654 : // protecting sandbox parameter strings
1655 0 : if ((rc = prot_strings(ctx, cfg))) {
1656 0 : goto end;
1657 : }
1658 :
1659 : // add parameter filters
1660 0 : if ((rc = add_param_filter(ctx, cfg))) {
1661 0 : log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1662 0 : goto end;
1663 : }
1664 :
1665 : // adding filters with no parameters
1666 0 : if ((rc = add_noparam_filter(ctx))) {
1667 0 : log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1668 0 : goto end;
1669 : }
1670 :
1671 : // loading the seccomp2 filter
1672 0 : if ((rc = seccomp_load(ctx))) {
1673 0 : log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)! "
1674 : "Are you sure that your kernel has seccomp2 support? The "
1675 : "sandbox won't work without it.", rc,
1676 : strerror(-rc));
1677 0 : goto end;
1678 : }
1679 :
1680 : // marking the sandbox as active
1681 0 : sandbox_active = 1;
1682 :
1683 0 : end:
1684 0 : seccomp_release(ctx);
1685 0 : return (rc < 0 ? -rc : rc);
1686 : }
1687 :
1688 : #ifdef SYSCALL_NAME_DEBUGGING
1689 : #include "lib/sandbox/linux_syscalls.inc"
1690 :
1691 : /** Return a string containing the name of a given syscall (if we know it) */
1692 : static const char *
1693 0 : get_syscall_name(int syscall_num)
1694 : {
1695 0 : int i;
1696 0 : for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
1697 0 : if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
1698 0 : return SYSCALLS_BY_NUMBER[i].syscall_name;
1699 : }
1700 :
1701 : {
1702 0 : static char syscall_name_buf[64];
1703 0 : format_dec_number_sigsafe(syscall_num,
1704 : syscall_name_buf, sizeof(syscall_name_buf));
1705 0 : return syscall_name_buf;
1706 : }
1707 : }
1708 :
1709 : /** Return the syscall number from a ucontext_t that we got in a signal
1710 : * handler (if we know how to do that). */
1711 : static int
1712 0 : get_syscall_from_ucontext(const ucontext_t *ctx)
1713 : {
1714 0 : return (int) ctx->uc_mcontext.M_SYSCALL;
1715 : }
1716 : #else /* !defined(SYSCALL_NAME_DEBUGGING) */
1717 : static const char *
1718 : get_syscall_name(int syscall_num)
1719 : {
1720 : (void) syscall_num;
1721 : return "unknown";
1722 : }
1723 : static int
1724 : get_syscall_from_ucontext(const ucontext_t *ctx)
1725 : {
1726 : (void) ctx;
1727 : return -1;
1728 : }
1729 : #endif /* defined(SYSCALL_NAME_DEBUGGING) */
1730 :
1731 : #ifdef USE_BACKTRACE
1732 : #define MAX_DEPTH 256
1733 : static void *syscall_cb_buf[MAX_DEPTH];
1734 : #endif
1735 :
1736 : /**
1737 : * Function called when a SIGSYS is caught by the application. It notifies the
1738 : * user that an error has occurred and either terminates or allows the
1739 : * application to continue execution, based on the DEBUGGING_CLOSE symbol.
1740 : */
1741 : static void
1742 0 : sigsys_debugging(int nr, siginfo_t *info, void *void_context)
1743 : {
1744 0 : ucontext_t *ctx = (ucontext_t *) (void_context);
1745 0 : const char *syscall_name;
1746 : #ifdef USE_BACKTRACE
1747 0 : size_t depth;
1748 0 : int n_fds, i;
1749 0 : const int *fds = NULL;
1750 : #endif
1751 :
1752 0 : (void) nr;
1753 :
1754 0 : if (info->si_code != SYS_SECCOMP)
1755 : return;
1756 :
1757 0 : if (!ctx)
1758 : return;
1759 :
1760 0 : int syscall = get_syscall_from_ucontext(ctx);
1761 :
1762 : #ifdef USE_BACKTRACE
1763 0 : depth = backtrace(syscall_cb_buf, MAX_DEPTH);
1764 : /* Clean up the top stack frame so we get the real function
1765 : * name for the most recently failing function. */
1766 0 : clean_backtrace(syscall_cb_buf, depth, ctx);
1767 : #endif /* defined(USE_BACKTRACE) */
1768 :
1769 0 : syscall_name = get_syscall_name(syscall);
1770 :
1771 0 : tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1772 : syscall_name,
1773 : ")\n",
1774 : NULL);
1775 :
1776 : #ifdef USE_BACKTRACE
1777 0 : n_fds = tor_log_get_sigsafe_err_fds(&fds);
1778 0 : for (i=0; i < n_fds; ++i)
1779 0 : backtrace_symbols_fd(syscall_cb_buf, (int)depth, fds[i]);
1780 : #endif
1781 :
1782 : #if defined(DEBUGGING_CLOSE)
1783 0 : _exit(1); // exit ok: programming error has led to sandbox failure.
1784 : #endif // DEBUGGING_CLOSE
1785 : }
1786 :
1787 : /**
1788 : * Function that adds a handler for SIGSYS, which is the signal thrown
1789 : * when the application is issuing a syscall which is not allowed. The
1790 : * main purpose of this function is to help with debugging by identifying
1791 : * filtered syscalls.
1792 : */
1793 : static int
1794 0 : install_sigsys_debugging(void)
1795 : {
1796 0 : struct sigaction act;
1797 0 : sigset_t mask;
1798 :
1799 0 : memset(&act, 0, sizeof(act));
1800 0 : sigemptyset(&mask);
1801 0 : sigaddset(&mask, SIGSYS);
1802 :
1803 0 : act.sa_sigaction = &sigsys_debugging;
1804 0 : act.sa_flags = SA_SIGINFO;
1805 0 : if (sigaction(SIGSYS, &act, NULL) < 0) {
1806 0 : log_err(LD_BUG,"(Sandbox) Failed to register SIGSYS signal handler");
1807 0 : return -1;
1808 : }
1809 :
1810 0 : if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
1811 0 : log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
1812 0 : return -2;
1813 : }
1814 :
1815 : return 0;
1816 : }
1817 :
1818 : /**
1819 : * Function responsible of registering the sandbox_cfg_t list of parameter
1820 : * syscall filters to the existing parameter list. This is used for incipient
1821 : * multiple-sandbox support.
1822 : */
1823 : static int
1824 0 : register_cfg(sandbox_cfg_t* cfg)
1825 : {
1826 0 : sandbox_cfg_t *elem = NULL;
1827 :
1828 0 : if (filter_dynamic == NULL) {
1829 0 : filter_dynamic = cfg;
1830 0 : return 0;
1831 : }
1832 :
1833 0 : for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
1834 : ;
1835 :
1836 0 : elem->next = cfg;
1837 :
1838 0 : return 0;
1839 : }
1840 :
1841 : #endif /* defined(USE_LIBSECCOMP) */
1842 :
1843 : #ifdef USE_LIBSECCOMP
1844 : /**
1845 : * Initialises the syscall sandbox filter for any linux architecture, taking
1846 : * into account various available features for different linux flavours.
1847 : */
1848 : static int
1849 0 : initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
1850 : {
1851 : /* Prevent glibc from trying to open /dev/tty on fatal error */
1852 0 : setenv("LIBC_FATAL_STDERR_", "1", 1);
1853 :
1854 0 : if (install_sigsys_debugging())
1855 : return -1;
1856 :
1857 0 : if (install_syscall_filter(cfg))
1858 : return -2;
1859 :
1860 0 : if (register_cfg(cfg))
1861 0 : return -3;
1862 :
1863 : return 0;
1864 : }
1865 :
1866 : int
1867 285 : sandbox_is_active(void)
1868 : {
1869 285 : return sandbox_active != 0;
1870 : }
1871 : #endif /* defined(USE_LIBSECCOMP) */
1872 :
1873 : sandbox_cfg_t*
1874 0 : sandbox_cfg_new(void)
1875 : {
1876 0 : return NULL;
1877 : }
1878 :
1879 : int
1880 0 : sandbox_init(sandbox_cfg_t *cfg)
1881 : {
1882 : #if defined(USE_LIBSECCOMP)
1883 0 : return initialise_libseccomp_sandbox(cfg);
1884 :
1885 : #elif defined(__linux__)
1886 : (void)cfg;
1887 : log_warn(LD_GENERAL,
1888 : "This version of Tor was built without support for sandboxing. To "
1889 : "build with support for sandboxing on Linux, you must have "
1890 : "libseccomp and its necessary header files (e.g. seccomp.h).");
1891 : return 0;
1892 :
1893 : #else
1894 : (void)cfg;
1895 : log_warn(LD_GENERAL,
1896 : "Currently, sandboxing is only implemented on Linux. The feature "
1897 : "is disabled on your platform.");
1898 : return 0;
1899 : #endif /* defined(USE_LIBSECCOMP) || ... */
1900 : }
1901 :
1902 : #ifndef USE_LIBSECCOMP
1903 : int
1904 : sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1905 : {
1906 : (void)cfg; (void)file;
1907 : return 0;
1908 : }
1909 :
1910 : int
1911 : sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1912 : {
1913 : (void)cfg; (void)file;
1914 : return 0;
1915 : }
1916 :
1917 : int
1918 : sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
1919 : {
1920 : (void)cfg; (void)dir;
1921 : return 0;
1922 : }
1923 :
1924 : int
1925 : sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1926 : {
1927 : (void)cfg; (void)file;
1928 : return 0;
1929 : }
1930 :
1931 : int
1932 : sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
1933 : {
1934 : (void)cfg; (void)file;
1935 : return 0;
1936 : }
1937 :
1938 : int
1939 : sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
1940 : {
1941 : (void)cfg; (void)file;
1942 : return 0;
1943 : }
1944 :
1945 : int
1946 : sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1947 : {
1948 : (void)cfg; (void)file1; (void)file2;
1949 : return 0;
1950 : }
1951 :
1952 : int
1953 : sandbox_is_active(void)
1954 : {
1955 : return 0;
1956 : }
1957 :
1958 : #endif /* !defined(USE_LIBSECCOMP) */
|