LCOV - code coverage report
Current view: top level - lib/sandbox - sandbox.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 12 475 2.5 %
Date: 2021-11-24 03:28:48 Functions: 4 53 7.5 %

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

Generated by: LCOV version 1.14