Tor  0.4.6.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-2020, 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 sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
321 {
322  unsigned i;
323  int rc;
324  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  (void) filter;
331 
332  for (i = 0; i < ARRAY_LENGTH(param); i++) {
333  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
334  SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
335  if (rc)
336  break;
337  }
338 
339  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 sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
348 {
349  (void) filter;
350 #ifdef __NR_time
351  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 sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
364 {
365  int rc = 0;
366  (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  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
377  SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
378  if (rc) {
379  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 is_libc_at_least(int major, int minor)
459 {
460 #ifdef CHECK_LIBC_VERSION
461  const char *version = gnu_get_libc_version();
462  if (version == NULL)
463  return 0;
464 
465  int libc_major = -1;
466  int libc_minor = -1;
467 
468  tor_sscanf(version, "%d.%d", &libc_major, &libc_minor);
469  if (libc_major > major)
470  return 1;
471  else if (libc_major == major && libc_minor >= minor)
472  return 1;
473  else
474  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 libc_uses_openat_for_open(void)
486 {
487  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 libc_uses_openat_for_opendir(void)
494 {
495  // libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
496  return is_libc_at_least(2, 27) ||
497  (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 libc_negative_constant_needs_cast(void)
504 {
505  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 allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
512 {
513  if (use_openat) {
514  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  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 sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
529 {
530  int rc;
531  sandbox_cfg_t *elem = NULL;
532 
533  int use_openat = libc_uses_openat_for_open();
534 
535  // for each dynamic parameter filters
536  for (elem = filter; elem != NULL; elem = elem->next) {
537  smp_param_t *param = elem->param;
538 
539  if (param != NULL && param->prot == 1 && param->syscall
540  == SCMP_SYS(open)) {
541  rc = allow_file_open(ctx, use_openat, param->value);
542  if (rc != 0) {
543  log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
544  "libseccomp error %d", rc);
545  return rc;
546  }
547  }
548  }
549 
550  return 0;
551 }
552 
553 static int
554 sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
555 {
556  int rc;
557  sandbox_cfg_t *elem = NULL;
558 
559  // for each dynamic parameter filters
560  for (elem = filter; elem != NULL; elem = elem->next) {
561  smp_param_t *param = elem->param;
562 
563  if (param != NULL && param->prot == 1 && param->syscall
564  == SCMP_SYS(chmod)) {
565  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
566  SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
567  if (rc != 0) {
568  log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
569  "libseccomp error %d", rc);
570  return rc;
571  }
572  }
573  }
574 
575  return 0;
576 }
577 
578 static int
579 sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
580 {
581  int rc;
582  sandbox_cfg_t *elem = NULL;
583 
584  // for each dynamic parameter filters
585  for (elem = filter; elem != NULL; elem = elem->next) {
586  smp_param_t *param = elem->param;
587 
588  if (param != NULL && param->prot == 1 && param->syscall
589  == SCMP_SYS(chown)) {
590  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
591  SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
592  if (rc != 0) {
593  log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
594  "libseccomp error %d", rc);
595  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 sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
609 {
610  int rc;
611  sandbox_cfg_t *elem = NULL;
612 
613  // for each dynamic parameter filters
614  for (elem = filter; elem != NULL; elem = elem->next) {
615  smp_param_t *param = elem->param;
616 
617  if (param != NULL && param->prot == 1 &&
618  param->syscall == SCMP_SYS(rename)) {
619 
620  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  if (rc != 0) {
624  log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
625  "libseccomp error %d", rc);
626  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 sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
640 {
641  int rc;
642  sandbox_cfg_t *elem = NULL;
643 
644  // for each dynamic parameter filters
645  for (elem = filter; elem != NULL; elem = elem->next) {
646  smp_param_t *param = elem->param;
647 
648  if (param != NULL && param->prot == 1 && param->syscall
649  == SCMP_SYS(openat)) {
650  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  if (rc != 0) {
656  log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
657  "libseccomp error %d", rc);
658  return rc;
659  }
660  }
661  }
662 
663  return 0;
664 }
665 
666 static int
667 sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
668 {
669  int rc;
670  sandbox_cfg_t *elem = NULL;
671 
672  // for each dynamic parameter filters
673  for (elem = filter; elem != NULL; elem = elem->next) {
674  smp_param_t *param = elem->param;
675 
676  if (param != NULL && param->prot == 1 && param->syscall
677  == PHONY_OPENDIR_SYSCALL) {
678  rc = allow_file_open(ctx, libc_uses_openat_for_opendir(), param->value);
679  if (rc != 0) {
680  log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
681  "libseccomp error %d", rc);
682  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 sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
696 {
697  int rc = 0;
698  int i, j;
699  (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  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  if (rc)
711  return rc;
712 
713  for (i = 0; i < 2; ++i) {
714  const int pf = i ? PF_INET : PF_INET6;
715  for (j=0; j < 3; ++j) {
716  const int type = (j == 0) ? SOCK_STREAM :
717  SOCK_DGRAM;
718  const int protocol = (j == 0) ? IPPROTO_TCP :
719  (j == 1) ? IPPROTO_IP :
720  IPPROTO_UDP;
721  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  if (rc)
726  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
738 
739  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  if (rc)
744  return rc;
745 
746  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  if (rc)
751  return rc;
752 
753  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  if (rc)
758  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 sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
769 {
770  int rc = 0;
771  (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  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  if (rc)
783  return rc;
784 
785  return 0;
786 }
787 
788 #ifdef HAVE_KIST_SUPPORT
789 
790 #include <linux/sockios.h>
791 
792 static int
793 sb_ioctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
794 {
795  int rc;
796  (void) filter;
797 
798  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
799  SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
800  if (rc)
801  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 sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
813 {
814  int rc = 0;
815  (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  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  if (rc)
827  return rc;
828 
829  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  if (rc)
833  return rc;
834 
835  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  if (rc)
839  return rc;
840 
841 #ifdef HAVE_SYSTEMD
842  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  if (rc)
846  return rc;
847 #endif /* defined(HAVE_SYSTEMD) */
848 
849 #ifdef IP_TRANSPARENT
850  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  if (rc)
854  return rc;
855 #endif /* defined(IP_TRANSPARENT) */
856 
857 #ifdef IPV6_V6ONLY
858  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  if (rc)
862  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 sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
874 {
875  int rc = 0;
876  (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  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  if (rc)
888  return rc;
889 
890  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  if (rc)
894  return rc;
895 
896 #ifdef HAVE_SYSTEMD
897  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  if (rc)
901  return rc;
902 #endif /* defined(HAVE_SYSTEMD) */
903 
904 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
905  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  if (rc)
909  return rc;
910 #endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
911 
912 #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
913  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  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  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  if (rc)
926  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 sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
977 {
978  int rc = 0;
979  (void) filter;
980 
981  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
982  SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
983  if (rc)
984  return rc;
985 
986  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
987  SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
988  if (rc)
989  return rc;
990 
991  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
992  SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
993  if (rc)
994  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 sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1008 {
1009  int rc = 0;
1010  (void) filter;
1011 
1012  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1013  SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
1014  if (rc)
1015  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 sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1029 {
1030  int rc = 0;
1031  (void) filter;
1032 
1033  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1034  SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
1035  if (rc)
1036  return rc;
1037 
1038  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1039  SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
1040  if (rc)
1041  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 sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1052 {
1053  int rc = 0;
1054  (void) filter;
1055 
1056  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1057  SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
1058  if (rc)
1059  return rc;
1060 
1061  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1062  SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
1063  if (rc)
1064  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 sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1077 {
1078  int rc = 0;
1079  (void) filter;
1080 
1081  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1082  SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
1083  if (rc)
1084  return rc;
1085 
1086  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1087  SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
1088  if (rc)
1089  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 sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1100 {
1101  int rc = 0;
1102  (void) filter;
1103 
1104  // can remove
1105  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  if (rc)
1109  return rc;
1110 
1111  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1112  SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
1113  if (rc)
1114  return rc;
1115 
1116  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1117  SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
1118  if (rc)
1119  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 sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1132 {
1133  int rc = 0;
1134  (void) filter;
1135 
1136  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
1137  SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
1138  if (rc)
1139  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 sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1177 {
1178  (void) filter;
1179 #ifdef __NR_kill
1180  /* Allow killing anything with signal 0 -- it isn't really a kill. */
1181  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 sandbox_intern_string(const char *str)
1237 {
1238  const char *interned = sandbox_get_interned_string(str);
1239 
1240  if (sandbox_active && str != NULL && interned == NULL) {
1241  log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
1242  }
1243 
1244  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 sandbox_interned_string_is_missing(const char *str)
1253 {
1254  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 sandbox_get_interned_string(const char *str)
1264 {
1265  sandbox_cfg_t *elem;
1266 
1267  if (str == NULL)
1268  return NULL;
1269 
1270  for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
1271  smp_param_t *param = elem->param;
1272 
1273  if (param->prot) {
1274  if (!strcmp(str, (char*)(param->value))) {
1275  return (char*)param->value;
1276  }
1277  if (param->value2 && !strcmp(str, (char*)param->value2)) {
1278  return (char*)param->value2;
1279  }
1280  }
1281  }
1282 
1283  return NULL;
1284 }
1285 
1286 /* DOCDOC */
1287 static int
1288 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  char *param_val;
1294  size_t param_size;
1295  void *location;
1296 
1297  if (*value_p == 0)
1298  return 0;
1299 
1300  param_val = (char*) *value_p;
1301  param_size = strlen(param_val) + 1;
1302  location = strmap_get(locations, param_val);
1303 
1304  if (location) {
1305  // We already interned this string.
1306  tor_free(param_val);
1307  *value_p = location;
1308  return 0;
1309  } else if (*pr_mem_left_p >= param_size) {
1310  // copy to protected
1311  location = *pr_mem_next_p;
1312  memcpy(location, param_val, param_size);
1313 
1314  // re-point el parameter to protected
1315  tor_free(param_val);
1316  *value_p = location;
1317 
1318  strmap_set(locations, location, location); /* good real estate advice */
1319 
1320  // move next available protected memory
1321  *pr_mem_next_p += param_size;
1322  *pr_mem_left_p -= param_size;
1323  return 0;
1324  } else {
1325  log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
1326  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 prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1338 {
1339  int ret = 0;
1340  size_t pr_mem_size = 0, pr_mem_left = 0;
1341  char *pr_mem_next = NULL, *pr_mem_base;
1342  sandbox_cfg_t *el = NULL;
1343  strmap_t *locations = NULL;
1344 
1345  // get total number of bytes required to mmap. (Overestimate.)
1346  for (el = cfg; el != NULL; el = el->next) {
1347  pr_mem_size += strlen((char*) el->param->value) + 1;
1348  if (el->param->value2)
1349  pr_mem_size += strlen((char*) el->param->value2) + 1;
1350  }
1351 
1352  // allocate protected memory with MALLOC_MP_LIM canary
1353  pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
1354  PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1355  if (pr_mem_base == MAP_FAILED) {
1356  log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
1357  strerror(errno));
1358  ret = -1;
1359  goto out;
1360  }
1361 
1362  pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
1363  pr_mem_left = pr_mem_size;
1364 
1365  locations = strmap_new();
1366 
1367  // change el value pointer to protected
1368  for (el = cfg; el != NULL; el = el->next) {
1369  if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1370  &el->param->value) < 0) {
1371  ret = -2;
1372  goto out;
1373  }
1374  if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1375  &el->param->value2) < 0) {
1376  ret = -2;
1377  goto out;
1378  }
1379  el->param->prot = 1;
1380  }
1381 
1382  // protecting from writes
1383  if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1384  log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
1385  strerror(errno));
1386  ret = -3;
1387  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  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  if (ret) {
1397  log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
1398  goto out;
1399  }
1400 
1401  // no munmap of the protected base address
1402  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  if (ret) {
1405  log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
1406  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  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  if (ret) {
1424  log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
1425  goto out;
1426  }
1427 
1428  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  if (ret) {
1434  log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
1435  goto out;
1436  }
1437 
1438  out:
1439  strmap_free(locations, NULL);
1440  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 new_element2(int syscall, char *value, char *value2)
1451 {
1452  smp_param_t *param = NULL;
1453 
1454  sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
1455  param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
1456 
1457  param->syscall = syscall;
1458  param->value = value;
1459  param->value2 = value2;
1460  param->prot = 0;
1461 
1462  return elem;
1463 }
1464 
1465 static sandbox_cfg_t*
1466 new_element(int syscall, char *value)
1467 {
1468  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
1479 {
1480  sandbox_cfg_t *elem = NULL;
1481 
1482  elem = new_element(SCMP_stat, file);
1483 
1484  elem->next = *cfg;
1485  *cfg = elem;
1486 
1487  return 0;
1488 }
1489 
1490 int
1492 {
1493  sandbox_cfg_t *elem = NULL;
1494 
1495  elem = new_element(SCMP_SYS(open), file);
1496 
1497  elem->next = *cfg;
1498  *cfg = elem;
1499 
1500  return 0;
1501 }
1502 
1503 int
1504 sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
1505 {
1506  sandbox_cfg_t *elem = NULL;
1507 
1508  elem = new_element(SCMP_SYS(chmod), file);
1509 
1510  elem->next = *cfg;
1511  *cfg = elem;
1512 
1513  return 0;
1514 }
1515 
1516 int
1517 sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
1518 {
1519  sandbox_cfg_t *elem = NULL;
1520 
1521  elem = new_element(SCMP_SYS(chown), file);
1522 
1523  elem->next = *cfg;
1524  *cfg = elem;
1525 
1526  return 0;
1527 }
1528 
1529 int
1530 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1531 {
1532  sandbox_cfg_t *elem = NULL;
1533 
1534  elem = new_element2(SCMP_SYS(rename), file1, file2);
1535 
1536  elem->next = *cfg;
1537  *cfg = elem;
1538 
1539  return 0;
1540 }
1541 
1542 int
1544 {
1545  sandbox_cfg_t *elem = NULL;
1546 
1547  elem = new_element(SCMP_SYS(openat), file);
1548 
1549  elem->next = *cfg;
1550  *cfg = elem;
1551 
1552  return 0;
1553 }
1554 
1555 int
1557 {
1558  sandbox_cfg_t *elem = NULL;
1559 
1560  elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
1561 
1562  elem->next = *cfg;
1563  *cfg = elem;
1564 
1565  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 add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1574 {
1575  unsigned i;
1576  int rc = 0;
1577 
1578  // function pointer
1579  for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
1580  rc = filter_func[i](ctx, cfg);
1581  if (rc) {
1582  log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
1583  "error %d", i, rc);
1584  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 add_noparam_filter(scmp_filter_ctx ctx)
1597 {
1598  unsigned i;
1599  int rc = 0;
1600 
1601  // add general filters
1602  for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
1603  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
1604  if (rc != 0) {
1605  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  return rc;
1608  }
1609  }
1610 
1611  return 0;
1612 }
1613 
1614 /**
1615  * Function responsible for setting up and enabling a global syscall filter.
1616  * The function is a prototype developed for stage 1 of sandboxing Tor.
1617  * Returns 0 on success.
1618  */
1619 static int
1620 install_syscall_filter(sandbox_cfg_t* cfg)
1621 {
1622  int rc = 0;
1623  scmp_filter_ctx ctx;
1624 
1625  ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
1626  if (ctx == NULL) {
1627  log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
1628  rc = -1;
1629  goto end;
1630  }
1631 
1632  // protecting sandbox parameter strings
1633  if ((rc = prot_strings(ctx, cfg))) {
1634  goto end;
1635  }
1636 
1637  // add parameter filters
1638  if ((rc = add_param_filter(ctx, cfg))) {
1639  log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1640  goto end;
1641  }
1642 
1643  // adding filters with no parameters
1644  if ((rc = add_noparam_filter(ctx))) {
1645  log_err(LD_BUG, "(Sandbox) failed to add param filters!");
1646  goto end;
1647  }
1648 
1649  // loading the seccomp2 filter
1650  if ((rc = seccomp_load(ctx))) {
1651  log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)! "
1652  "Are you sure that your kernel has seccomp2 support? The "
1653  "sandbox won't work without it.", rc,
1654  strerror(-rc));
1655  goto end;
1656  }
1657 
1658  // marking the sandbox as active
1659  sandbox_active = 1;
1660 
1661  end:
1662  seccomp_release(ctx);
1663  return (rc < 0 ? -rc : rc);
1664 }
1665 
1666 #ifdef SYSCALL_NAME_DEBUGGING
1667 #include "lib/sandbox/linux_syscalls.inc"
1668 
1669 /** Return a string containing the name of a given syscall (if we know it) */
1670 static const char *
1671 get_syscall_name(int syscall_num)
1672 {
1673  int i;
1674  for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
1675  if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
1676  return SYSCALLS_BY_NUMBER[i].syscall_name;
1677  }
1678 
1679  {
1680  static char syscall_name_buf[64];
1681  format_dec_number_sigsafe(syscall_num,
1682  syscall_name_buf, sizeof(syscall_name_buf));
1683  return syscall_name_buf;
1684  }
1685 }
1686 
1687 /** Return the syscall number from a ucontext_t that we got in a signal
1688  * handler (if we know how to do that). */
1689 static int
1690 get_syscall_from_ucontext(const ucontext_t *ctx)
1691 {
1692  return (int) ctx->uc_mcontext.M_SYSCALL;
1693 }
1694 #else
1695 static const char *
1696 get_syscall_name(int syscall_num)
1697 {
1698  (void) syscall_num;
1699  return "unknown";
1700 }
1701 static int
1702 get_syscall_from_ucontext(const ucontext_t *ctx)
1703 {
1704  (void) ctx;
1705  return -1;
1706 }
1707 #endif
1708 
1709 #ifdef USE_BACKTRACE
1710 #define MAX_DEPTH 256
1711 static void *syscall_cb_buf[MAX_DEPTH];
1712 #endif
1713 
1714 /**
1715  * Function called when a SIGSYS is caught by the application. It notifies the
1716  * user that an error has occurred and either terminates or allows the
1717  * application to continue execution, based on the DEBUGGING_CLOSE symbol.
1718  */
1719 static void
1720 sigsys_debugging(int nr, siginfo_t *info, void *void_context)
1721 {
1722  ucontext_t *ctx = (ucontext_t *) (void_context);
1723  const char *syscall_name;
1724 #ifdef USE_BACKTRACE
1725  size_t depth;
1726  int n_fds, i;
1727  const int *fds = NULL;
1728 #endif
1729 
1730  (void) nr;
1731 
1732  if (info->si_code != SYS_SECCOMP)
1733  return;
1734 
1735  if (!ctx)
1736  return;
1737 
1738  int syscall = get_syscall_from_ucontext(ctx);
1739 
1740 #ifdef USE_BACKTRACE
1741  depth = backtrace(syscall_cb_buf, MAX_DEPTH);
1742  /* Clean up the top stack frame so we get the real function
1743  * name for the most recently failing function. */
1744  clean_backtrace(syscall_cb_buf, depth, ctx);
1745 #endif /* defined(USE_BACKTRACE) */
1746 
1747  syscall_name = get_syscall_name(syscall);
1748 
1749  tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
1750  syscall_name,
1751  ")\n",
1752  NULL);
1753 
1754 #ifdef USE_BACKTRACE
1755  n_fds = tor_log_get_sigsafe_err_fds(&fds);
1756  for (i=0; i < n_fds; ++i)
1757  backtrace_symbols_fd(syscall_cb_buf, (int)depth, fds[i]);
1758 #endif
1759 
1760 #if defined(DEBUGGING_CLOSE)
1761  _exit(1); // exit ok: programming error has led to sandbox failure.
1762 #endif // DEBUGGING_CLOSE
1763 }
1764 
1765 /**
1766  * Function that adds a handler for SIGSYS, which is the signal thrown
1767  * when the application is issuing a syscall which is not allowed. The
1768  * main purpose of this function is to help with debugging by identifying
1769  * filtered syscalls.
1770  */
1771 static int
1772 install_sigsys_debugging(void)
1773 {
1774  struct sigaction act;
1775  sigset_t mask;
1776 
1777  memset(&act, 0, sizeof(act));
1778  sigemptyset(&mask);
1779  sigaddset(&mask, SIGSYS);
1780 
1781  act.sa_sigaction = &sigsys_debugging;
1782  act.sa_flags = SA_SIGINFO;
1783  if (sigaction(SIGSYS, &act, NULL) < 0) {
1784  log_err(LD_BUG,"(Sandbox) Failed to register SIGSYS signal handler");
1785  return -1;
1786  }
1787 
1788  if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
1789  log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
1790  return -2;
1791  }
1792 
1793  return 0;
1794 }
1795 
1796 /**
1797  * Function responsible of registering the sandbox_cfg_t list of parameter
1798  * syscall filters to the existing parameter list. This is used for incipient
1799  * multiple-sandbox support.
1800  */
1801 static int
1802 register_cfg(sandbox_cfg_t* cfg)
1803 {
1804  sandbox_cfg_t *elem = NULL;
1805 
1806  if (filter_dynamic == NULL) {
1807  filter_dynamic = cfg;
1808  return 0;
1809  }
1810 
1811  for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
1812  ;
1813 
1814  elem->next = cfg;
1815 
1816  return 0;
1817 }
1818 
1819 #endif /* defined(USE_LIBSECCOMP) */
1820 
1821 #ifdef USE_LIBSECCOMP
1822 /**
1823  * Initialises the syscall sandbox filter for any linux architecture, taking
1824  * into account various available features for different linux flavours.
1825  */
1826 static int
1827 initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
1828 {
1829  /* Prevent glibc from trying to open /dev/tty on fatal error */
1830  setenv("LIBC_FATAL_STDERR_", "1", 1);
1831 
1832  if (install_sigsys_debugging())
1833  return -1;
1834 
1835  if (install_syscall_filter(cfg))
1836  return -2;
1837 
1838  if (register_cfg(cfg))
1839  return -3;
1840 
1841  return 0;
1842 }
1843 
1844 int
1845 sandbox_is_active(void)
1846 {
1847  return sandbox_active != 0;
1848 }
1849 #endif /* defined(USE_LIBSECCOMP) */
1850 
1853 {
1854  return NULL;
1855 }
1856 
1857 int
1859 {
1860 #if defined(USE_LIBSECCOMP)
1861  return initialise_libseccomp_sandbox(cfg);
1862 
1863 #elif defined(__linux__)
1864  (void)cfg;
1865  log_warn(LD_GENERAL,
1866  "This version of Tor was built without support for sandboxing. To "
1867  "build with support for sandboxing on Linux, you must have "
1868  "libseccomp and its necessary header files (e.g. seccomp.h).");
1869  return 0;
1870 
1871 #else
1872  (void)cfg;
1873  log_warn(LD_GENERAL,
1874  "Currently, sandboxing is only implemented on Linux. The feature "
1875  "is disabled on your platform.");
1876  return 0;
1877 #endif /* defined(USE_LIBSECCOMP) || ... */
1878 }
1879 
1880 #ifndef USE_LIBSECCOMP
1881 int
1883 {
1884  (void)cfg; (void)file;
1885  return 0;
1886 }
1887 
1888 int
1890 {
1891  (void)cfg; (void)file;
1892  return 0;
1893 }
1894 
1895 int
1897 {
1898  (void)cfg; (void)dir;
1899  return 0;
1900 }
1901 
1902 int
1904 {
1905  (void)cfg; (void)file;
1906  return 0;
1907 }
1908 
1909 int
1910 sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
1911 {
1912  (void)cfg; (void)file;
1913  return 0;
1914 }
1915 
1916 int
1917 sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
1918 {
1919  (void)cfg; (void)file;
1920  return 0;
1921 }
1922 
1923 int
1924 sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1925 {
1926  (void)cfg; (void)file1; (void)file2;
1927  return 0;
1928 }
1929 
1930 int
1932 {
1933  return 0;
1934 }
1935 
1936 #endif /* !defined(USE_LIBSECCOMP) */
tor_free
#define tor_free(p)
Definition: malloc.h:52
tor_log_get_sigsafe_err_fds
int tor_log_get_sigsafe_err_fds(const int **out)
Definition: torerr.c:103
sandbox.h
Header file for sandbox.c.
LD_BUG
#define LD_BUG
Definition: log.h:86
LD_GENERAL
#define LD_GENERAL
Definition: log.h:62
sandbox_cfg_allow_openat_filename
int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
Definition: sandbox.c:1889
sandbox_cfg_allow_open_filename
int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
Definition: sandbox.c:1882
backtrace.h
Header for backtrace.c.
torint.h
Integer definitions used throughout Tor.
sandbox_is_active
int sandbox_is_active(void)
Definition: sandbox.c:1931
SYS_SECCOMP
#define SYS_SECCOMP
Definition: sandbox.h:24
sandbox_intern_string
#define sandbox_intern_string(s)
Definition: sandbox.h:110
sandbox_cfg_allow_opendir_dirname
int sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
Definition: sandbox.c:1896
sandbox_init
int sandbox_init(sandbox_cfg_t *cfg)
Definition: sandbox.c:1858
time.h
Definitions for timing-related constants.
scanf.h
Header for scanf.c.
malloc.h
Headers for util_malloc.c.
tor_sscanf
int tor_sscanf(const char *buf, const char *pattern,...)
Definition: scanf.c:309
MALLOC_MP_LIM
#define MALLOC_MP_LIM
Definition: sandbox.c:29
map.h
Headers for map.c.
ARRAY_LENGTH
#define ARRAY_LENGTH(x)
Definition: compat_compiler.h:222
log.h
Headers for log.c.
sandbox_cfg_allow_stat_filename
int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
Definition: sandbox.c:1903
sandbox_cfg_new
sandbox_cfg_t * sandbox_cfg_new(void)
Definition: sandbox.c:1852
torerr.h
Headers for torerr.c.
tor_log_err_sigsafe
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
format_dec_number_sigsafe
int format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
Definition: torerr.c:305
sandbox_cfg_t
struct sandbox_cfg_elem_t sandbox_cfg_t
Definition: sandbox.h:35