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