LCOV - code coverage report
Current view: top level - src/util - syscall_sandbox.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 2 2 100.0 %
Date: 2022-04-21 14:51:19 Functions: 1 1 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 0 0 -

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2020-2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #if defined(HAVE_CONFIG_H)
#       6                 :            : #include <config/bitcoin-config.h>
#       7                 :            : #endif // defined(HAVE_CONFIG_H)
#       8                 :            : 
#       9                 :            : #include <util/syscall_sandbox.h>
#      10                 :            : 
#      11                 :            : #if defined(USE_SYSCALL_SANDBOX)
#      12                 :            : #include <array>
#      13                 :            : #include <cassert>
#      14                 :            : #include <cstdint>
#      15                 :            : #include <exception>
#      16                 :            : #include <map>
#      17                 :            : #include <new>
#      18                 :            : #include <set>
#      19                 :            : #include <string>
#      20                 :            : #include <vector>
#      21                 :            : 
#      22                 :            : #include <logging.h>
#      23                 :            : #include <tinyformat.h>
#      24                 :            : #include <util/threadnames.h>
#      25                 :            : 
#      26                 :            : #include <linux/audit.h>
#      27                 :            : #include <linux/filter.h>
#      28                 :            : #include <linux/seccomp.h>
#      29                 :            : #include <linux/unistd.h>
#      30                 :            : #include <signal.h>
#      31                 :            : #include <sys/prctl.h>
#      32                 :            : #include <sys/types.h>
#      33                 :            : #include <unistd.h>
#      34                 :            : 
#      35                 :            : namespace {
#      36                 :            : bool g_syscall_sandbox_enabled{false};
#      37                 :            : bool g_syscall_sandbox_log_violation_before_terminating{false};
#      38                 :            : 
#      39                 :            : #if !defined(__x86_64__)
#      40                 :            : #error Syscall sandbox is an experimental feature currently available only under Linux x86-64.
#      41                 :            : #endif // defined(__x86_64__)
#      42                 :            : 
#      43                 :            : #ifndef SECCOMP_RET_KILL_PROCESS
#      44                 :            : #define SECCOMP_RET_KILL_PROCESS 0x80000000U
#      45                 :            : #endif
#      46                 :            : 
#      47                 :            : // Define system call numbers for x86_64 that are referenced in the system call profile
#      48                 :            : // but not provided by the kernel headers used in the GUIX build.
#      49                 :            : // Usually, they can be found via "grep name /usr/include/x86_64-linux-gnu/asm/unistd_64.h"
#      50                 :            : 
#      51                 :            : #ifndef __NR_clone3
#      52                 :            : #define __NR_clone3 435
#      53                 :            : #endif
#      54                 :            : 
#      55                 :            : #ifndef __NR_statx
#      56                 :            : #define __NR_statx 332
#      57                 :            : #endif
#      58                 :            : 
#      59                 :            : #ifndef __NR_getrandom
#      60                 :            : #define __NR_getrandom 318
#      61                 :            : #endif
#      62                 :            : 
#      63                 :            : #ifndef __NR_membarrier
#      64                 :            : #define __NR_membarrier 324
#      65                 :            : #endif
#      66                 :            : 
#      67                 :            : #ifndef __NR_copy_file_range
#      68                 :            : #define __NR_copy_file_range 326
#      69                 :            : #endif
#      70                 :            : 
#      71                 :            : #ifndef  __NR_rseq
#      72                 :            : #define __NR_rseq 334
#      73                 :            : #endif
#      74                 :            : 
#      75                 :            : // This list of syscalls in LINUX_SYSCALLS is only used to map syscall numbers to syscall names in
#      76                 :            : // order to be able to print user friendly error messages which include the syscall name in addition
#      77                 :            : // to the syscall number.
#      78                 :            : //
#      79                 :            : // Example output in case of a syscall violation where the syscall is present in LINUX_SYSCALLS:
#      80                 :            : //
#      81                 :            : // ```
#      82                 :            : // 2021-06-09T12:34:56Z ERROR: The syscall "execve" (syscall number 59) is not allowed by the syscall sandbox in thread "msghand". Please report.
#      83                 :            : // ```
#      84                 :            : //
#      85                 :            : // Example output in case of a syscall violation where the syscall is not present in LINUX_SYSCALLS:
#      86                 :            : //
#      87                 :            : // ```
#      88                 :            : // 2021-06-09T12:34:56Z ERROR: The syscall "*unknown*" (syscall number 314) is not allowed by the syscall sandbox in thread "msghand". Please report.
#      89                 :            : // ``
#      90                 :            : //
#      91                 :            : // LINUX_SYSCALLS contains two types of syscalls:
#      92                 :            : // 1.) Syscalls that are present under all architectures or relevant Linux kernel versions for which
#      93                 :            : //     we support the syscall sandbox feature (currently only Linux x86-64). Examples include read,
#      94                 :            : //     write, open, close, etc.
#      95                 :            : // 2.) Syscalls that are present under a subset of architectures or relevant Linux kernel versions
#      96                 :            : //     for which we support the syscall sandbox feature. This type of syscalls should be added to
#      97                 :            : //     LINUX_SYSCALLS conditional on availability like in the following example:
#      98                 :            : //         ...
#      99                 :            : //         #if defined(__NR_arch_dependent_syscall)
#     100                 :            : //             {__NR_arch_dependent_syscall, "arch_dependent_syscall"},
#     101                 :            : //         #endif // defined(__NR_arch_dependent_syscall)
#     102                 :            : //         ...
#     103                 :            : const std::map<uint32_t, std::string> LINUX_SYSCALLS{
#     104                 :            :     {__NR_accept, "accept"},
#     105                 :            :     {__NR_accept4, "accept4"},
#     106                 :            :     {__NR_access, "access"},
#     107                 :            :     {__NR_acct, "acct"},
#     108                 :            :     {__NR_add_key, "add_key"},
#     109                 :            :     {__NR_adjtimex, "adjtimex"},
#     110                 :            :     {__NR_afs_syscall, "afs_syscall"},
#     111                 :            :     {__NR_alarm, "alarm"},
#     112                 :            :     {__NR_arch_prctl, "arch_prctl"},
#     113                 :            :     {__NR_bind, "bind"},
#     114                 :            :     {__NR_bpf, "bpf"},
#     115                 :            :     {__NR_brk, "brk"},
#     116                 :            :     {__NR_capget, "capget"},
#     117                 :            :     {__NR_capset, "capset"},
#     118                 :            :     {__NR_chdir, "chdir"},
#     119                 :            :     {__NR_chmod, "chmod"},
#     120                 :            :     {__NR_chown, "chown"},
#     121                 :            :     {__NR_chroot, "chroot"},
#     122                 :            :     {__NR_clock_adjtime, "clock_adjtime"},
#     123                 :            :     {__NR_clock_getres, "clock_getres"},
#     124                 :            :     {__NR_clock_gettime, "clock_gettime"},
#     125                 :            :     {__NR_clock_nanosleep, "clock_nanosleep"},
#     126                 :            :     {__NR_clock_settime, "clock_settime"},
#     127                 :            :     {__NR_clone, "clone"},
#     128                 :            :     {__NR_clone3, "clone3"},
#     129                 :            :     {__NR_close, "close"},
#     130                 :            :     {__NR_connect, "connect"},
#     131                 :            :     {__NR_copy_file_range, "copy_file_range"},
#     132                 :            :     {__NR_creat, "creat"},
#     133                 :            :     {__NR_create_module, "create_module"},
#     134                 :            :     {__NR_delete_module, "delete_module"},
#     135                 :            :     {__NR_dup, "dup"},
#     136                 :            :     {__NR_dup2, "dup2"},
#     137                 :            :     {__NR_dup3, "dup3"},
#     138                 :            :     {__NR_epoll_create, "epoll_create"},
#     139                 :            :     {__NR_epoll_create1, "epoll_create1"},
#     140                 :            :     {__NR_epoll_ctl, "epoll_ctl"},
#     141                 :            :     {__NR_epoll_ctl_old, "epoll_ctl_old"},
#     142                 :            :     {__NR_epoll_pwait, "epoll_pwait"},
#     143                 :            :     {__NR_epoll_wait, "epoll_wait"},
#     144                 :            :     {__NR_epoll_wait_old, "epoll_wait_old"},
#     145                 :            :     {__NR_eventfd, "eventfd"},
#     146                 :            :     {__NR_eventfd2, "eventfd2"},
#     147                 :            :     {__NR_execve, "execve"},
#     148                 :            :     {__NR_execveat, "execveat"},
#     149                 :            :     {__NR_exit, "exit"},
#     150                 :            :     {__NR_exit_group, "exit_group"},
#     151                 :            :     {__NR_faccessat, "faccessat"},
#     152                 :            :     {__NR_fadvise64, "fadvise64"},
#     153                 :            :     {__NR_fallocate, "fallocate"},
#     154                 :            :     {__NR_fanotify_init, "fanotify_init"},
#     155                 :            :     {__NR_fanotify_mark, "fanotify_mark"},
#     156                 :            :     {__NR_fchdir, "fchdir"},
#     157                 :            :     {__NR_fchmod, "fchmod"},
#     158                 :            :     {__NR_fchmodat, "fchmodat"},
#     159                 :            :     {__NR_fchown, "fchown"},
#     160                 :            :     {__NR_fchownat, "fchownat"},
#     161                 :            :     {__NR_fcntl, "fcntl"},
#     162                 :            :     {__NR_fdatasync, "fdatasync"},
#     163                 :            :     {__NR_fgetxattr, "fgetxattr"},
#     164                 :            :     {__NR_finit_module, "finit_module"},
#     165                 :            :     {__NR_flistxattr, "flistxattr"},
#     166                 :            :     {__NR_flock, "flock"},
#     167                 :            :     {__NR_fork, "fork"},
#     168                 :            :     {__NR_fremovexattr, "fremovexattr"},
#     169                 :            :     {__NR_fsetxattr, "fsetxattr"},
#     170                 :            :     {__NR_fstat, "fstat"},
#     171                 :            :     {__NR_fstatfs, "fstatfs"},
#     172                 :            :     {__NR_fsync, "fsync"},
#     173                 :            :     {__NR_ftruncate, "ftruncate"},
#     174                 :            :     {__NR_futex, "futex"},
#     175                 :            :     {__NR_futimesat, "futimesat"},
#     176                 :            :     {__NR_get_kernel_syms, "get_kernel_syms"},
#     177                 :            :     {__NR_get_mempolicy, "get_mempolicy"},
#     178                 :            :     {__NR_get_robust_list, "get_robust_list"},
#     179                 :            :     {__NR_get_thread_area, "get_thread_area"},
#     180                 :            :     {__NR_getcpu, "getcpu"},
#     181                 :            :     {__NR_getcwd, "getcwd"},
#     182                 :            :     {__NR_getdents, "getdents"},
#     183                 :            :     {__NR_getdents64, "getdents64"},
#     184                 :            :     {__NR_getegid, "getegid"},
#     185                 :            :     {__NR_geteuid, "geteuid"},
#     186                 :            :     {__NR_getgid, "getgid"},
#     187                 :            :     {__NR_getgroups, "getgroups"},
#     188                 :            :     {__NR_getitimer, "getitimer"},
#     189                 :            :     {__NR_getpeername, "getpeername"},
#     190                 :            :     {__NR_getpgid, "getpgid"},
#     191                 :            :     {__NR_getpgrp, "getpgrp"},
#     192                 :            :     {__NR_getpid, "getpid"},
#     193                 :            :     {__NR_getpmsg, "getpmsg"},
#     194                 :            :     {__NR_getppid, "getppid"},
#     195                 :            :     {__NR_getpriority, "getpriority"},
#     196                 :            :     {__NR_getrandom, "getrandom"},
#     197                 :            :     {__NR_getresgid, "getresgid"},
#     198                 :            :     {__NR_getresuid, "getresuid"},
#     199                 :            :     {__NR_getrlimit, "getrlimit"},
#     200                 :            :     {__NR_getrusage, "getrusage"},
#     201                 :            :     {__NR_getsid, "getsid"},
#     202                 :            :     {__NR_getsockname, "getsockname"},
#     203                 :            :     {__NR_getsockopt, "getsockopt"},
#     204                 :            :     {__NR_gettid, "gettid"},
#     205                 :            :     {__NR_gettimeofday, "gettimeofday"},
#     206                 :            :     {__NR_getuid, "getuid"},
#     207                 :            :     {__NR_getxattr, "getxattr"},
#     208                 :            :     {__NR_init_module, "init_module"},
#     209                 :            :     {__NR_inotify_add_watch, "inotify_add_watch"},
#     210                 :            :     {__NR_inotify_init, "inotify_init"},
#     211                 :            :     {__NR_inotify_init1, "inotify_init1"},
#     212                 :            :     {__NR_inotify_rm_watch, "inotify_rm_watch"},
#     213                 :            :     {__NR_io_cancel, "io_cancel"},
#     214                 :            :     {__NR_io_destroy, "io_destroy"},
#     215                 :            :     {__NR_io_getevents, "io_getevents"},
#     216                 :            :     {__NR_io_setup, "io_setup"},
#     217                 :            :     {__NR_io_submit, "io_submit"},
#     218                 :            :     {__NR_ioctl, "ioctl"},
#     219                 :            :     {__NR_ioperm, "ioperm"},
#     220                 :            :     {__NR_iopl, "iopl"},
#     221                 :            :     {__NR_ioprio_get, "ioprio_get"},
#     222                 :            :     {__NR_ioprio_set, "ioprio_set"},
#     223                 :            :     {__NR_kcmp, "kcmp"},
#     224                 :            :     {__NR_kexec_file_load, "kexec_file_load"},
#     225                 :            :     {__NR_kexec_load, "kexec_load"},
#     226                 :            :     {__NR_keyctl, "keyctl"},
#     227                 :            :     {__NR_kill, "kill"},
#     228                 :            :     {__NR_lchown, "lchown"},
#     229                 :            :     {__NR_lgetxattr, "lgetxattr"},
#     230                 :            :     {__NR_link, "link"},
#     231                 :            :     {__NR_linkat, "linkat"},
#     232                 :            :     {__NR_listen, "listen"},
#     233                 :            :     {__NR_listxattr, "listxattr"},
#     234                 :            :     {__NR_llistxattr, "llistxattr"},
#     235                 :            :     {__NR_lookup_dcookie, "lookup_dcookie"},
#     236                 :            :     {__NR_lremovexattr, "lremovexattr"},
#     237                 :            :     {__NR_lseek, "lseek"},
#     238                 :            :     {__NR_lsetxattr, "lsetxattr"},
#     239                 :            :     {__NR_lstat, "lstat"},
#     240                 :            :     {__NR_madvise, "madvise"},
#     241                 :            :     {__NR_mbind, "mbind"},
#     242                 :            :     {__NR_membarrier, "membarrier"},
#     243                 :            :     {__NR_memfd_create, "memfd_create"},
#     244                 :            :     {__NR_migrate_pages, "migrate_pages"},
#     245                 :            :     {__NR_mincore, "mincore"},
#     246                 :            :     {__NR_mkdir, "mkdir"},
#     247                 :            :     {__NR_mkdirat, "mkdirat"},
#     248                 :            :     {__NR_mknod, "mknod"},
#     249                 :            :     {__NR_mknodat, "mknodat"},
#     250                 :            :     {__NR_mlock, "mlock"},
#     251                 :            :     {__NR_mlock2, "mlock2"},
#     252                 :            :     {__NR_mlockall, "mlockall"},
#     253                 :            :     {__NR_mmap, "mmap"},
#     254                 :            :     {__NR_modify_ldt, "modify_ldt"},
#     255                 :            :     {__NR_mount, "mount"},
#     256                 :            :     {__NR_move_pages, "move_pages"},
#     257                 :            :     {__NR_mprotect, "mprotect"},
#     258                 :            :     {__NR_mq_getsetattr, "mq_getsetattr"},
#     259                 :            :     {__NR_mq_notify, "mq_notify"},
#     260                 :            :     {__NR_mq_open, "mq_open"},
#     261                 :            :     {__NR_mq_timedreceive, "mq_timedreceive"},
#     262                 :            :     {__NR_mq_timedsend, "mq_timedsend"},
#     263                 :            :     {__NR_mq_unlink, "mq_unlink"},
#     264                 :            :     {__NR_mremap, "mremap"},
#     265                 :            :     {__NR_msgctl, "msgctl"},
#     266                 :            :     {__NR_msgget, "msgget"},
#     267                 :            :     {__NR_msgrcv, "msgrcv"},
#     268                 :            :     {__NR_msgsnd, "msgsnd"},
#     269                 :            :     {__NR_msync, "msync"},
#     270                 :            :     {__NR_munlock, "munlock"},
#     271                 :            :     {__NR_munlockall, "munlockall"},
#     272                 :            :     {__NR_munmap, "munmap"},
#     273                 :            :     {__NR_name_to_handle_at, "name_to_handle_at"},
#     274                 :            :     {__NR_nanosleep, "nanosleep"},
#     275                 :            :     {__NR_newfstatat, "newfstatat"},
#     276                 :            :     {__NR_nfsservctl, "nfsservctl"},
#     277                 :            :     {__NR_open, "open"},
#     278                 :            :     {__NR_open_by_handle_at, "open_by_handle_at"},
#     279                 :            :     {__NR_openat, "openat"},
#     280                 :            :     {__NR_pause, "pause"},
#     281                 :            :     {__NR_perf_event_open, "perf_event_open"},
#     282                 :            :     {__NR_personality, "personality"},
#     283                 :            :     {__NR_pipe, "pipe"},
#     284                 :            :     {__NR_pipe2, "pipe2"},
#     285                 :            :     {__NR_pivot_root, "pivot_root"},
#     286                 :            : #ifdef __NR_pkey_alloc
#     287                 :            :     {__NR_pkey_alloc, "pkey_alloc"},
#     288                 :            : #endif
#     289                 :            : #ifdef __NR_pkey_free
#     290                 :            :     {__NR_pkey_free, "pkey_free"},
#     291                 :            : #endif
#     292                 :            : #ifdef __NR_pkey_mprotect
#     293                 :            :     {__NR_pkey_mprotect, "pkey_mprotect"},
#     294                 :            : #endif
#     295                 :            :     {__NR_poll, "poll"},
#     296                 :            :     {__NR_ppoll, "ppoll"},
#     297                 :            :     {__NR_prctl, "prctl"},
#     298                 :            :     {__NR_pread64, "pread64"},
#     299                 :            :     {__NR_preadv, "preadv"},
#     300                 :            : #ifdef __NR_preadv2
#     301                 :            :     {__NR_preadv2, "preadv2"},
#     302                 :            : #endif
#     303                 :            :     {__NR_prlimit64, "prlimit64"},
#     304                 :            :     {__NR_process_vm_readv, "process_vm_readv"},
#     305                 :            :     {__NR_process_vm_writev, "process_vm_writev"},
#     306                 :            :     {__NR_pselect6, "pselect6"},
#     307                 :            :     {__NR_ptrace, "ptrace"},
#     308                 :            :     {__NR_putpmsg, "putpmsg"},
#     309                 :            :     {__NR_pwrite64, "pwrite64"},
#     310                 :            :     {__NR_pwritev, "pwritev"},
#     311                 :            : #ifdef __NR_pwritev2
#     312                 :            :     {__NR_pwritev2, "pwritev2"},
#     313                 :            : #endif
#     314                 :            :     {__NR__sysctl, "_sysctl"},
#     315                 :            :     {__NR_query_module, "query_module"},
#     316                 :            :     {__NR_quotactl, "quotactl"},
#     317                 :            :     {__NR_read, "read"},
#     318                 :            :     {__NR_readahead, "readahead"},
#     319                 :            :     {__NR_readlink, "readlink"},
#     320                 :            :     {__NR_readlinkat, "readlinkat"},
#     321                 :            :     {__NR_readv, "readv"},
#     322                 :            :     {__NR_reboot, "reboot"},
#     323                 :            :     {__NR_recvfrom, "recvfrom"},
#     324                 :            :     {__NR_recvmmsg, "recvmmsg"},
#     325                 :            :     {__NR_recvmsg, "recvmsg"},
#     326                 :            :     {__NR_remap_file_pages, "remap_file_pages"},
#     327                 :            :     {__NR_removexattr, "removexattr"},
#     328                 :            :     {__NR_rename, "rename"},
#     329                 :            :     {__NR_renameat, "renameat"},
#     330                 :            :     {__NR_renameat2, "renameat2"},
#     331                 :            :     {__NR_request_key, "request_key"},
#     332                 :            :     {__NR_restart_syscall, "restart_syscall"},
#     333                 :            :     {__NR_rmdir, "rmdir"},
#     334                 :            :     {__NR_rseq, "rseq"},
#     335                 :            :     {__NR_rt_sigaction, "rt_sigaction"},
#     336                 :            :     {__NR_rt_sigpending, "rt_sigpending"},
#     337                 :            :     {__NR_rt_sigprocmask, "rt_sigprocmask"},
#     338                 :            :     {__NR_rt_sigqueueinfo, "rt_sigqueueinfo"},
#     339                 :            :     {__NR_rt_sigreturn, "rt_sigreturn"},
#     340                 :            :     {__NR_rt_sigsuspend, "rt_sigsuspend"},
#     341                 :            :     {__NR_rt_sigtimedwait, "rt_sigtimedwait"},
#     342                 :            :     {__NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo"},
#     343                 :            :     {__NR_sched_get_priority_max, "sched_get_priority_max"},
#     344                 :            :     {__NR_sched_get_priority_min, "sched_get_priority_min"},
#     345                 :            :     {__NR_sched_getaffinity, "sched_getaffinity"},
#     346                 :            :     {__NR_sched_getattr, "sched_getattr"},
#     347                 :            :     {__NR_sched_getparam, "sched_getparam"},
#     348                 :            :     {__NR_sched_getscheduler, "sched_getscheduler"},
#     349                 :            :     {__NR_sched_rr_get_interval, "sched_rr_get_interval"},
#     350                 :            :     {__NR_sched_setaffinity, "sched_setaffinity"},
#     351                 :            :     {__NR_sched_setattr, "sched_setattr"},
#     352                 :            :     {__NR_sched_setparam, "sched_setparam"},
#     353                 :            :     {__NR_sched_setscheduler, "sched_setscheduler"},
#     354                 :            :     {__NR_sched_yield, "sched_yield"},
#     355                 :            :     {__NR_seccomp, "seccomp"},
#     356                 :            :     {__NR_security, "security"},
#     357                 :            :     {__NR_select, "select"},
#     358                 :            :     {__NR_semctl, "semctl"},
#     359                 :            :     {__NR_semget, "semget"},
#     360                 :            :     {__NR_semop, "semop"},
#     361                 :            :     {__NR_semtimedop, "semtimedop"},
#     362                 :            :     {__NR_sendfile, "sendfile"},
#     363                 :            :     {__NR_sendmmsg, "sendmmsg"},
#     364                 :            :     {__NR_sendmsg, "sendmsg"},
#     365                 :            :     {__NR_sendto, "sendto"},
#     366                 :            :     {__NR_set_mempolicy, "set_mempolicy"},
#     367                 :            :     {__NR_set_robust_list, "set_robust_list"},
#     368                 :            :     {__NR_set_thread_area, "set_thread_area"},
#     369                 :            :     {__NR_set_tid_address, "set_tid_address"},
#     370                 :            :     {__NR_setdomainname, "setdomainname"},
#     371                 :            :     {__NR_setfsgid, "setfsgid"},
#     372                 :            :     {__NR_setfsuid, "setfsuid"},
#     373                 :            :     {__NR_setgid, "setgid"},
#     374                 :            :     {__NR_setgroups, "setgroups"},
#     375                 :            :     {__NR_sethostname, "sethostname"},
#     376                 :            :     {__NR_setitimer, "setitimer"},
#     377                 :            :     {__NR_setns, "setns"},
#     378                 :            :     {__NR_setpgid, "setpgid"},
#     379                 :            :     {__NR_setpriority, "setpriority"},
#     380                 :            :     {__NR_setregid, "setregid"},
#     381                 :            :     {__NR_setresgid, "setresgid"},
#     382                 :            :     {__NR_setresuid, "setresuid"},
#     383                 :            :     {__NR_setreuid, "setreuid"},
#     384                 :            :     {__NR_setrlimit, "setrlimit"},
#     385                 :            :     {__NR_setsid, "setsid"},
#     386                 :            :     {__NR_setsockopt, "setsockopt"},
#     387                 :            :     {__NR_settimeofday, "settimeofday"},
#     388                 :            :     {__NR_setuid, "setuid"},
#     389                 :            :     {__NR_setxattr, "setxattr"},
#     390                 :            :     {__NR_shmat, "shmat"},
#     391                 :            :     {__NR_shmctl, "shmctl"},
#     392                 :            :     {__NR_shmdt, "shmdt"},
#     393                 :            :     {__NR_shmget, "shmget"},
#     394                 :            :     {__NR_shutdown, "shutdown"},
#     395                 :            :     {__NR_sigaltstack, "sigaltstack"},
#     396                 :            :     {__NR_signalfd, "signalfd"},
#     397                 :            :     {__NR_signalfd4, "signalfd4"},
#     398                 :            :     {__NR_socket, "socket"},
#     399                 :            :     {__NR_socketpair, "socketpair"},
#     400                 :            :     {__NR_splice, "splice"},
#     401                 :            :     {__NR_stat, "stat"},
#     402                 :            :     {__NR_statfs, "statfs"},
#     403                 :            :     {__NR_statx, "statx"},
#     404                 :            :     {__NR_swapoff, "swapoff"},
#     405                 :            :     {__NR_swapon, "swapon"},
#     406                 :            :     {__NR_symlink, "symlink"},
#     407                 :            :     {__NR_symlinkat, "symlinkat"},
#     408                 :            :     {__NR_sync, "sync"},
#     409                 :            :     {__NR_sync_file_range, "sync_file_range"},
#     410                 :            :     {__NR_syncfs, "syncfs"},
#     411                 :            :     {__NR_sysfs, "sysfs"},
#     412                 :            :     {__NR_sysinfo, "sysinfo"},
#     413                 :            :     {__NR_syslog, "syslog"},
#     414                 :            :     {__NR_tee, "tee"},
#     415                 :            :     {__NR_tgkill, "tgkill"},
#     416                 :            :     {__NR_time, "time"},
#     417                 :            :     {__NR_timer_create, "timer_create"},
#     418                 :            :     {__NR_timer_delete, "timer_delete"},
#     419                 :            :     {__NR_timer_getoverrun, "timer_getoverrun"},
#     420                 :            :     {__NR_timer_gettime, "timer_gettime"},
#     421                 :            :     {__NR_timer_settime, "timer_settime"},
#     422                 :            :     {__NR_timerfd_create, "timerfd_create"},
#     423                 :            :     {__NR_timerfd_gettime, "timerfd_gettime"},
#     424                 :            :     {__NR_timerfd_settime, "timerfd_settime"},
#     425                 :            :     {__NR_times, "times"},
#     426                 :            :     {__NR_tkill, "tkill"},
#     427                 :            :     {__NR_truncate, "truncate"},
#     428                 :            :     {__NR_tuxcall, "tuxcall"},
#     429                 :            :     {__NR_umask, "umask"},
#     430                 :            :     {__NR_umount2, "umount2"},
#     431                 :            :     {__NR_uname, "uname"},
#     432                 :            :     {__NR_unlink, "unlink"},
#     433                 :            :     {__NR_unlinkat, "unlinkat"},
#     434                 :            :     {__NR_unshare, "unshare"},
#     435                 :            :     {__NR_uselib, "uselib"},
#     436                 :            :     {__NR_userfaultfd, "userfaultfd"},
#     437                 :            :     {__NR_ustat, "ustat"},
#     438                 :            :     {__NR_utime, "utime"},
#     439                 :            :     {__NR_utimensat, "utimensat"},
#     440                 :            :     {__NR_utimes, "utimes"},
#     441                 :            :     {__NR_vfork, "vfork"},
#     442                 :            :     {__NR_vhangup, "vhangup"},
#     443                 :            :     {__NR_vmsplice, "vmsplice"},
#     444                 :            :     {__NR_vserver, "vserver"},
#     445                 :            :     {__NR_wait4, "wait4"},
#     446                 :            :     {__NR_waitid, "waitid"},
#     447                 :            :     {__NR_write, "write"},
#     448                 :            :     {__NR_writev, "writev"},
#     449                 :            : };
#     450                 :            : 
#     451                 :            : std::string GetLinuxSyscallName(uint32_t syscall_number)
#     452                 :            : {
#     453                 :            :     const auto element = LINUX_SYSCALLS.find(syscall_number);
#     454                 :            :     if (element != LINUX_SYSCALLS.end()) {
#     455                 :            :         return element->second;
#     456                 :            :     }
#     457                 :            :     return "*unknown*";
#     458                 :            : }
#     459                 :            : 
#     460                 :            : // See Linux kernel developer Kees Cook's seccomp guide at <https://outflux.net/teach-seccomp/> for
#     461                 :            : // an accessible introduction to using seccomp.
#     462                 :            : //
#     463                 :            : // This function largely follows <https://outflux.net/teach-seccomp/step-3/syscall-reporter.c> and
#     464                 :            : // <https://outflux.net/teach-seccomp/step-3/seccomp-bpf.h>.
#     465                 :            : //
#     466                 :            : // Seccomp BPF resources:
#     467                 :            : // * Seccomp BPF documentation: <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
#     468                 :            : // * seccomp(2) manual page: <https://www.kernel.org/doc/man-pages/online/pages/man2/seccomp.2.html>
#     469                 :            : // * Seccomp BPF demo code samples: <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/seccomp>
#     470                 :            : void SyscallSandboxDebugSignalHandler(int, siginfo_t* signal_info, void* void_signal_context)
#     471                 :            : {
#     472                 :            :     // The si_code field inside the siginfo_t argument that is passed to a SA_SIGINFO signal handler
#     473                 :            :     // is a value indicating why the signal was sent.
#     474                 :            :     //
#     475                 :            :     // The following value can be placed in si_code for a SIGSYS signal:
#     476                 :            :     // * SYS_SECCOMP (since Linux 3.5): Triggered by a seccomp(2) filter rule.
#     477                 :            :     constexpr int32_t SYS_SECCOMP_SI_CODE{1};
#     478                 :            :     assert(signal_info->si_code == SYS_SECCOMP_SI_CODE);
#     479                 :            : 
#     480                 :            :     // The ucontext_t structure contains signal context information that was saved on the user-space
#     481                 :            :     // stack by the kernel.
#     482                 :            :     const ucontext_t* signal_context = static_cast<ucontext_t*>(void_signal_context);
#     483                 :            :     assert(signal_context != nullptr);
#     484                 :            : 
#     485                 :            :     std::set_new_handler(std::terminate);
#     486                 :            :     // Portability note: REG_RAX is Linux x86_64 specific.
#     487                 :            :     const uint32_t syscall_number = static_cast<uint32_t>(signal_context->uc_mcontext.gregs[REG_RAX]);
#     488                 :            :     const std::string syscall_name = GetLinuxSyscallName(syscall_number);
#     489                 :            :     const std::string thread_name = !util::ThreadGetInternalName().empty() ? util::ThreadGetInternalName() : "*unnamed*";
#     490                 :            :     const std::string error_message = strprintf("ERROR: The syscall \"%s\" (syscall number %d) is not allowed by the syscall sandbox in thread \"%s\". Please report.", syscall_name, syscall_number, thread_name);
#     491                 :            :     tfm::format(std::cerr, "%s\n", error_message);
#     492                 :            :     LogPrintf("%s\n", error_message);
#     493                 :            :     std::terminate();
#     494                 :            : }
#     495                 :            : 
#     496                 :            : // This function largely follows install_syscall_reporter from Kees Cook's seccomp guide:
#     497                 :            : // <https://outflux.net/teach-seccomp/step-3/syscall-reporter.c>
#     498                 :            : bool SetupSyscallSandboxDebugHandler()
#     499                 :            : {
#     500                 :            :     struct sigaction action = {};
#     501                 :            :     sigset_t mask;
#     502                 :            :     sigemptyset(&mask);
#     503                 :            :     sigaddset(&mask, SIGSYS);
#     504                 :            :     action.sa_sigaction = &SyscallSandboxDebugSignalHandler;
#     505                 :            :     action.sa_flags = SA_SIGINFO;
#     506                 :            :     if (sigaction(SIGSYS, &action, nullptr) < 0) {
#     507                 :            :         return false;
#     508                 :            :     }
#     509                 :            :     if (sigprocmask(SIG_UNBLOCK, &mask, nullptr)) {
#     510                 :            :         return false;
#     511                 :            :     }
#     512                 :            :     return true;
#     513                 :            : }
#     514                 :            : 
#     515                 :            : enum class SyscallSandboxAction {
#     516                 :            :     KILL_PROCESS,
#     517                 :            :     INVOKE_SIGNAL_HANDLER,
#     518                 :            : };
#     519                 :            : 
#     520                 :            : class SeccompPolicyBuilder
#     521                 :            : {
#     522                 :            :     std::set<uint32_t> allowed_syscalls;
#     523                 :            : 
#     524                 :            : public:
#     525                 :            :     SeccompPolicyBuilder()
#     526                 :            :     {
#     527                 :            :         // Allowed by default.
#     528                 :            :         AllowAddressSpaceAccess();
#     529                 :            :         AllowEpoll();
#     530                 :            :         AllowEventFd();
#     531                 :            :         AllowFutex();
#     532                 :            :         AllowGeneralIo();
#     533                 :            :         AllowGetRandom();
#     534                 :            :         AllowGetSimpleId();
#     535                 :            :         AllowGetTime();
#     536                 :            :         AllowGlobalProcessEnvironment();
#     537                 :            :         AllowGlobalSystemStatus();
#     538                 :            :         AllowKernelInternalApi();
#     539                 :            :         AllowNetworkSocketInformation();
#     540                 :            :         AllowOperationOnExistingFileDescriptor();
#     541                 :            :         AllowPipe();
#     542                 :            :         AllowPrctl();
#     543                 :            :         AllowProcessStartOrDeath();
#     544                 :            :         AllowScheduling();
#     545                 :            :         AllowSignalHandling();
#     546                 :            :         AllowSleep();
#     547                 :            :         AllowUmask();
#     548                 :            :     }
#     549                 :            : 
#     550                 :            :     void AllowAddressSpaceAccess()
#     551                 :            :     {
#     552                 :            :         allowed_syscalls.insert(__NR_brk);        // change data segment size
#     553                 :            :         allowed_syscalls.insert(__NR_madvise);    // give advice about use of memory
#     554                 :            :         allowed_syscalls.insert(__NR_membarrier); // issue memory barriers on a set of threads
#     555                 :            :         allowed_syscalls.insert(__NR_mincore);    // check if virtual memory is in RAM
#     556                 :            :         allowed_syscalls.insert(__NR_mlock);      // lock memory
#     557                 :            :         allowed_syscalls.insert(__NR_mmap);       // map files or devices into memory
#     558                 :            :         allowed_syscalls.insert(__NR_mprotect);   // set protection on a region of memory
#     559                 :            :         allowed_syscalls.insert(__NR_mremap);     // remap a file in memory
#     560                 :            :         allowed_syscalls.insert(__NR_munlock);    // unlock memory
#     561                 :            :         allowed_syscalls.insert(__NR_munmap);     // unmap files or devices into memory
#     562                 :            :     }
#     563                 :            : 
#     564                 :            :     void AllowEpoll()
#     565                 :            :     {
#     566                 :            :         allowed_syscalls.insert(__NR_epoll_create1); // open an epoll file descriptor
#     567                 :            :         allowed_syscalls.insert(__NR_epoll_ctl);     // control interface for an epoll file descriptor
#     568                 :            :         allowed_syscalls.insert(__NR_epoll_pwait);   // wait for an I/O event on an epoll file descriptor
#     569                 :            :         allowed_syscalls.insert(__NR_epoll_wait);    // wait for an I/O event on an epoll file descriptor
#     570                 :            :     }
#     571                 :            : 
#     572                 :            :     void AllowEventFd()
#     573                 :            :     {
#     574                 :            :         allowed_syscalls.insert(__NR_eventfd2); // create a file descriptor for event notification
#     575                 :            :     }
#     576                 :            : 
#     577                 :            :     void AllowFileSystem()
#     578                 :            :     {
#     579                 :            :         allowed_syscalls.insert(__NR_access);          // check user's permissions for a file
#     580                 :            :         allowed_syscalls.insert(__NR_chdir);           // change working directory
#     581                 :            :         allowed_syscalls.insert(__NR_chmod);           // change permissions of a file
#     582                 :            :         allowed_syscalls.insert(__NR_copy_file_range); // copy a range of data from one file to another
#     583                 :            :         allowed_syscalls.insert(__NR_fallocate);       // manipulate file space
#     584                 :            :         allowed_syscalls.insert(__NR_fchmod);          // change permissions of a file
#     585                 :            :         allowed_syscalls.insert(__NR_fchown);          // change ownership of a file
#     586                 :            :         allowed_syscalls.insert(__NR_fdatasync);       // synchronize a file's in-core state with storage device
#     587                 :            :         allowed_syscalls.insert(__NR_flock);           // apply or remove an advisory lock on an open file
#     588                 :            :         allowed_syscalls.insert(__NR_fstat);           // get file status
#     589                 :            :         allowed_syscalls.insert(__NR_fstatfs);         // get file system status
#     590                 :            :         allowed_syscalls.insert(__NR_fsync);           // synchronize a file's in-core state with storage device
#     591                 :            :         allowed_syscalls.insert(__NR_ftruncate);       // truncate a file to a specified length
#     592                 :            :         allowed_syscalls.insert(__NR_getcwd);          // get current working directory
#     593                 :            :         allowed_syscalls.insert(__NR_getdents);        // get directory entries
#     594                 :            :         allowed_syscalls.insert(__NR_getdents64);      // get directory entries
#     595                 :            :         allowed_syscalls.insert(__NR_lstat);           // get file status
#     596                 :            :         allowed_syscalls.insert(__NR_mkdir);           // create a directory
#     597                 :            :         allowed_syscalls.insert(__NR_newfstatat);      // get file status
#     598                 :            :         allowed_syscalls.insert(__NR_open);            // open and possibly create a file
#     599                 :            :         allowed_syscalls.insert(__NR_openat);          // open and possibly create a file
#     600                 :            :         allowed_syscalls.insert(__NR_readlink);        // read value of a symbolic link
#     601                 :            :         allowed_syscalls.insert(__NR_rename);          // change the name or location of a file
#     602                 :            :         allowed_syscalls.insert(__NR_rmdir);           // delete a directory
#     603                 :            :         allowed_syscalls.insert(__NR_sendfile);        // transfer data between file descriptors
#     604                 :            :         allowed_syscalls.insert(__NR_stat);            // get file status
#     605                 :            :         allowed_syscalls.insert(__NR_statfs);          // get filesystem statistics
#     606                 :            :         allowed_syscalls.insert(__NR_statx);           // get file status (extended)
#     607                 :            :         allowed_syscalls.insert(__NR_unlink);          // delete a name and possibly the file it refers to
#     608                 :            :         allowed_syscalls.insert(__NR_unlinkat);        // delete relative to a directory file descriptor
#     609                 :            :     }
#     610                 :            : 
#     611                 :            :     void AllowFutex()
#     612                 :            :     {
#     613                 :            :         allowed_syscalls.insert(__NR_futex);           // fast user-space locking
#     614                 :            :         allowed_syscalls.insert(__NR_set_robust_list); // set list of robust futexes
#     615                 :            :     }
#     616                 :            : 
#     617                 :            :     void AllowGeneralIo()
#     618                 :            :     {
#     619                 :            :         allowed_syscalls.insert(__NR_ioctl);    // control device
#     620                 :            :         allowed_syscalls.insert(__NR_lseek);    // reposition read/write file offset
#     621                 :            :         allowed_syscalls.insert(__NR_poll);     // wait for some event on a file descriptor
#     622                 :            :         allowed_syscalls.insert(__NR_ppoll);    // wait for some event on a file descriptor
#     623                 :            :         allowed_syscalls.insert(__NR_pread64);  // read from a file descriptor at a given offset
#     624                 :            :         allowed_syscalls.insert(__NR_pwrite64); // write to a file descriptor at a given offset
#     625                 :            :         allowed_syscalls.insert(__NR_read);     // read from a file descriptor
#     626                 :            :         allowed_syscalls.insert(__NR_readv);    // read data into multiple buffers
#     627                 :            :         allowed_syscalls.insert(__NR_recvfrom); // receive a message from a socket
#     628                 :            :         allowed_syscalls.insert(__NR_recvmsg);  // receive a message from a socket
#     629                 :            :         allowed_syscalls.insert(__NR_select);   // synchronous I/O multiplexing
#     630                 :            :         allowed_syscalls.insert(__NR_sendmmsg); // send multiple messages on a socket
#     631                 :            :         allowed_syscalls.insert(__NR_sendmsg);  // send a message on a socket
#     632                 :            :         allowed_syscalls.insert(__NR_sendto);   // send a message on a socket
#     633                 :            :         allowed_syscalls.insert(__NR_write);    // write to a file descriptor
#     634                 :            :         allowed_syscalls.insert(__NR_writev);   // write data into multiple buffers
#     635                 :            :     }
#     636                 :            : 
#     637                 :            :     void AllowGetRandom()
#     638                 :            :     {
#     639                 :            :         allowed_syscalls.insert(__NR_getrandom); // obtain a series of random bytes
#     640                 :            :     }
#     641                 :            : 
#     642                 :            :     void AllowGetSimpleId()
#     643                 :            :     {
#     644                 :            :         allowed_syscalls.insert(__NR_getegid);   // get group identity
#     645                 :            :         allowed_syscalls.insert(__NR_geteuid);   // get user identity
#     646                 :            :         allowed_syscalls.insert(__NR_getgid);    // get group identity
#     647                 :            :         allowed_syscalls.insert(__NR_getpgid);   // get process group
#     648                 :            :         allowed_syscalls.insert(__NR_getpid);    // get process identification
#     649                 :            :         allowed_syscalls.insert(__NR_getppid);   // get process identification
#     650                 :            :         allowed_syscalls.insert(__NR_getresgid); // get real, effective and saved group IDs
#     651                 :            :         allowed_syscalls.insert(__NR_getresuid); // get real, effective and saved user IDs
#     652                 :            :         allowed_syscalls.insert(__NR_getsid);    // get session ID
#     653                 :            :         allowed_syscalls.insert(__NR_gettid);    // get thread identification
#     654                 :            :         allowed_syscalls.insert(__NR_getuid);    // get user identity
#     655                 :            :     }
#     656                 :            : 
#     657                 :            :     void AllowGetTime()
#     658                 :            :     {
#     659                 :            :         allowed_syscalls.insert(__NR_clock_getres);  // find the resolution (precision) of the specified clock
#     660                 :            :         allowed_syscalls.insert(__NR_clock_gettime); // retrieve the time of the specified clock
#     661                 :            :         allowed_syscalls.insert(__NR_gettimeofday);  // get timeval
#     662                 :            :     }
#     663                 :            : 
#     664                 :            :     void AllowGlobalProcessEnvironment()
#     665                 :            :     {
#     666                 :            :         allowed_syscalls.insert(__NR_getrlimit); // get resource limits
#     667                 :            :         allowed_syscalls.insert(__NR_getrusage); // get resource usage
#     668                 :            :         allowed_syscalls.insert(__NR_prlimit64); // get/set resource limits
#     669                 :            :     }
#     670                 :            : 
#     671                 :            :     void AllowGlobalSystemStatus()
#     672                 :            :     {
#     673                 :            :         allowed_syscalls.insert(__NR_sysinfo); // return system information
#     674                 :            :         allowed_syscalls.insert(__NR_uname);   // get name and information about current kernel
#     675                 :            :     }
#     676                 :            : 
#     677                 :            :     void AllowKernelInternalApi()
#     678                 :            :     {
#     679                 :            :         allowed_syscalls.insert(__NR_restart_syscall); // restart a system call after interruption by a stop signal
#     680                 :            :     }
#     681                 :            : 
#     682                 :            :     void AllowNetwork()
#     683                 :            :     {
#     684                 :            :         allowed_syscalls.insert(__NR_accept);     // accept a connection on a socket
#     685                 :            :         allowed_syscalls.insert(__NR_accept4);    // accept a connection on a socket
#     686                 :            :         allowed_syscalls.insert(__NR_bind);       // bind a name to a socket
#     687                 :            :         allowed_syscalls.insert(__NR_connect);    // initiate a connection on a socket
#     688                 :            :         allowed_syscalls.insert(__NR_listen);     // listen for connections on a socket
#     689                 :            :         allowed_syscalls.insert(__NR_setsockopt); // set options on sockets
#     690                 :            :         allowed_syscalls.insert(__NR_socket);     // create an endpoint for communication
#     691                 :            :         allowed_syscalls.insert(__NR_socketpair); // create a pair of connected sockets
#     692                 :            :     }
#     693                 :            : 
#     694                 :            :     void AllowNetworkSocketInformation()
#     695                 :            :     {
#     696                 :            :         allowed_syscalls.insert(__NR_getpeername); // get name of connected peer socket
#     697                 :            :         allowed_syscalls.insert(__NR_getsockname); // get socket name
#     698                 :            :         allowed_syscalls.insert(__NR_getsockopt);  // get options on sockets
#     699                 :            :     }
#     700                 :            : 
#     701                 :            :     void AllowOperationOnExistingFileDescriptor()
#     702                 :            :     {
#     703                 :            :         allowed_syscalls.insert(__NR_close);    // close a file descriptor
#     704                 :            :         allowed_syscalls.insert(__NR_dup);      // duplicate a file descriptor
#     705                 :            :         allowed_syscalls.insert(__NR_dup2);     // duplicate a file descriptor
#     706                 :            :         allowed_syscalls.insert(__NR_fcntl);    // manipulate file descriptor
#     707                 :            :         allowed_syscalls.insert(__NR_shutdown); // shut down part of a full-duplex connection
#     708                 :            :     }
#     709                 :            : 
#     710                 :            :     void AllowPipe()
#     711                 :            :     {
#     712                 :            :         allowed_syscalls.insert(__NR_pipe);  // create pipe
#     713                 :            :         allowed_syscalls.insert(__NR_pipe2); // create pipe
#     714                 :            :     }
#     715                 :            : 
#     716                 :            :     void AllowPrctl()
#     717                 :            :     {
#     718                 :            :         allowed_syscalls.insert(__NR_arch_prctl); // set architecture-specific thread state
#     719                 :            :         allowed_syscalls.insert(__NR_prctl);      // operations on a process
#     720                 :            :     }
#     721                 :            : 
#     722                 :            :     void AllowProcessStartOrDeath()
#     723                 :            :     {
#     724                 :            :         allowed_syscalls.insert(__NR_clone);      // create a child process
#     725                 :            :         allowed_syscalls.insert(__NR_clone3);     // create a child process
#     726                 :            :         allowed_syscalls.insert(__NR_exit);       // terminate the calling process
#     727                 :            :         allowed_syscalls.insert(__NR_exit_group); // exit all threads in a process
#     728                 :            :         allowed_syscalls.insert(__NR_fork);       // create a child process
#     729                 :            :         allowed_syscalls.insert(__NR_tgkill);     // send a signal to a thread
#     730                 :            :         allowed_syscalls.insert(__NR_wait4);      // wait for process to change state, BSD style
#     731                 :            :         allowed_syscalls.insert(__NR_rseq);       // register restartable sequence for thread
#     732                 :            :     }
#     733                 :            : 
#     734                 :            :     void AllowScheduling()
#     735                 :            :     {
#     736                 :            :         allowed_syscalls.insert(__NR_sched_getaffinity);  // set a thread's CPU affinity mask
#     737                 :            :         allowed_syscalls.insert(__NR_sched_getparam);     // get scheduling parameters
#     738                 :            :         allowed_syscalls.insert(__NR_sched_getscheduler); // get scheduling policy/parameters
#     739                 :            :         allowed_syscalls.insert(__NR_sched_setscheduler); // set scheduling policy/parameters
#     740                 :            :         allowed_syscalls.insert(__NR_sched_yield);        // yield the processor
#     741                 :            :     }
#     742                 :            : 
#     743                 :            :     void AllowSignalHandling()
#     744                 :            :     {
#     745                 :            :         allowed_syscalls.insert(__NR_rt_sigaction);   // examine and change a signal action
#     746                 :            :         allowed_syscalls.insert(__NR_rt_sigprocmask); // examine and change blocked signals
#     747                 :            :         allowed_syscalls.insert(__NR_rt_sigreturn);   // return from signal handler and cleanup stack frame
#     748                 :            :         allowed_syscalls.insert(__NR_sigaltstack);    // set and/or get signal stack context
#     749                 :            :     }
#     750                 :            : 
#     751                 :            :     void AllowSleep()
#     752                 :            :     {
#     753                 :            :         allowed_syscalls.insert(__NR_clock_nanosleep); // high-resolution sleep with specifiable clock
#     754                 :            :         allowed_syscalls.insert(__NR_nanosleep);       // high-resolution sleep
#     755                 :            :     }
#     756                 :            : 
#     757                 :            :     void AllowUmask()
#     758                 :            :     {
#     759                 :            :         allowed_syscalls.insert(__NR_umask); // set file mode creation mask
#     760                 :            :     }
#     761                 :            : 
#     762                 :            :     // See Linux kernel developer Kees Cook's seccomp guide at <https://outflux.net/teach-seccomp/>
#     763                 :            :     // for an accessible introduction to using seccomp.
#     764                 :            :     //
#     765                 :            :     // This function largely follows <https://outflux.net/teach-seccomp/step-3/seccomp-bpf.h>.
#     766                 :            :     std::vector<sock_filter> BuildFilter(SyscallSandboxAction default_action)
#     767                 :            :     {
#     768                 :            :         std::vector<sock_filter> bpf_policy;
#     769                 :            :         // See VALIDATE_ARCHITECTURE in seccomp-bpf.h referenced above.
#     770                 :            :         bpf_policy.push_back(BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, arch)));
#     771                 :            :         // Portability note: AUDIT_ARCH_X86_64 is Linux x86_64 specific.
#     772                 :            :         bpf_policy.push_back(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, AUDIT_ARCH_X86_64, 1, 0));
#     773                 :            :         bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS));
#     774                 :            :         // See EXAMINE_SYSCALL in seccomp-bpf.h referenced above.
#     775                 :            :         bpf_policy.push_back(BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr)));
#     776                 :            :         for (const uint32_t allowed_syscall : allowed_syscalls) {
#     777                 :            :             // See ALLOW_SYSCALL in seccomp-bpf.h referenced above.
#     778                 :            :             bpf_policy.push_back(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, allowed_syscall, 0, 1));
#     779                 :            :             bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW));
#     780                 :            :         }
#     781                 :            :         switch (default_action) {
#     782                 :            :         case SyscallSandboxAction::KILL_PROCESS:
#     783                 :            :             // Disallow syscall and kill the process.
#     784                 :            :             //
#     785                 :            :             // See KILL_PROCESS in seccomp-bpf.h referenced above.
#     786                 :            :             //
#     787                 :            :             // Note that we're using SECCOMP_RET_KILL_PROCESS (kill the process) instead
#     788                 :            :             // of SECCOMP_RET_KILL_THREAD (kill the thread). The SECCOMP_RET_KILL_PROCESS
#     789                 :            :             // action was introduced in Linux 4.14.
#     790                 :            :             //
#     791                 :            :             // SECCOMP_RET_KILL_PROCESS: Results in the entire process exiting immediately without
#     792                 :            :             // executing the system call.
#     793                 :            :             //
#     794                 :            :             // SECCOMP_RET_KILL_PROCESS documentation:
#     795                 :            :             // <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
#     796                 :            :             bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS));
#     797                 :            :             break;
#     798                 :            :         case SyscallSandboxAction::INVOKE_SIGNAL_HANDLER:
#     799                 :            :             // Disallow syscall and force a SIGSYS to trigger syscall debug reporter.
#     800                 :            :             //
#     801                 :            :             // SECCOMP_RET_TRAP: Results in the kernel sending a SIGSYS signal to the triggering
#     802                 :            :             // task without executing the system call.
#     803                 :            :             //
#     804                 :            :             // SECCOMP_RET_TRAP documentation:
#     805                 :            :             // <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
#     806                 :            :             bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP));
#     807                 :            :             break;
#     808                 :            :         }
#     809                 :            :         return bpf_policy;
#     810                 :            :     }
#     811                 :            : };
#     812                 :            : } // namespace
#     813                 :            : 
#     814                 :            : bool SetupSyscallSandbox(bool log_syscall_violation_before_terminating)
#     815                 :            : {
#     816                 :            :     assert(!g_syscall_sandbox_enabled && "SetupSyscallSandbox(...) should only be called once.");
#     817                 :            :     g_syscall_sandbox_enabled = true;
#     818                 :            :     g_syscall_sandbox_log_violation_before_terminating = log_syscall_violation_before_terminating;
#     819                 :            :     if (log_syscall_violation_before_terminating) {
#     820                 :            :         if (!SetupSyscallSandboxDebugHandler()) {
#     821                 :            :             return false;
#     822                 :            :         }
#     823                 :            :     }
#     824                 :            :     return true;
#     825                 :            : }
#     826                 :            : 
#     827                 :            : void TestDisallowedSandboxCall()
#     828                 :            : {
#     829                 :            :     // The getgroups syscall is assumed NOT to be allowed by the syscall sandbox policy.
#     830                 :            :     std::array<gid_t, 1> groups;
#     831                 :            :     [[maybe_unused]] int32_t ignored = getgroups(groups.size(), groups.data());
#     832                 :            : }
#     833                 :            : #endif // defined(USE_SYSCALL_SANDBOX)
#     834                 :            : 
#     835                 :            : void SetSyscallSandboxPolicy(SyscallSandboxPolicy syscall_policy)
#     836                 :      14711 : {
#     837                 :            : #if defined(USE_SYSCALL_SANDBOX)
#     838                 :            :     if (!g_syscall_sandbox_enabled) {
#     839                 :            :         return;
#     840                 :            :     }
#     841                 :            :     SeccompPolicyBuilder seccomp_policy_builder;
#     842                 :            :     switch (syscall_policy) {
#     843                 :            :     case SyscallSandboxPolicy::INITIALIZATION: // Thread: main thread (state: init)
#     844                 :            :         // SyscallSandboxPolicy::INITIALIZATION is the first policy loaded.
#     845                 :            :         //
#     846                 :            :         // Subsequently loaded policies can reduce the abilities further, but
#     847                 :            :         // abilities can never be regained.
#     848                 :            :         //
#     849                 :            :         // SyscallSandboxPolicy::INITIALIZATION must thus be a superset of all
#     850                 :            :         // other policies.
#     851                 :            :         seccomp_policy_builder.AllowFileSystem();
#     852                 :            :         seccomp_policy_builder.AllowNetwork();
#     853                 :            :         break;
#     854                 :            :     case SyscallSandboxPolicy::INITIALIZATION_DNS_SEED: // Thread: dnsseed
#     855                 :            :         seccomp_policy_builder.AllowFileSystem();
#     856                 :            :         seccomp_policy_builder.AllowNetwork();
#     857                 :            :         break;
#     858                 :            :     case SyscallSandboxPolicy::INITIALIZATION_LOAD_BLOCKS: // Thread: loadblk
#     859                 :            :         seccomp_policy_builder.AllowFileSystem();
#     860                 :            :         break;
#     861                 :            :     case SyscallSandboxPolicy::INITIALIZATION_MAP_PORT: // Thread: mapport
#     862                 :            :         seccomp_policy_builder.AllowFileSystem();
#     863                 :            :         seccomp_policy_builder.AllowNetwork();
#     864                 :            :         break;
#     865                 :            :     case SyscallSandboxPolicy::MESSAGE_HANDLER: // Thread: msghand
#     866                 :            :         seccomp_policy_builder.AllowFileSystem();
#     867                 :            :         break;
#     868                 :            :     case SyscallSandboxPolicy::NET: // Thread: net
#     869                 :            :         seccomp_policy_builder.AllowFileSystem();
#     870                 :            :         seccomp_policy_builder.AllowNetwork();
#     871                 :            :         break;
#     872                 :            :     case SyscallSandboxPolicy::NET_ADD_CONNECTION: // Thread: addcon
#     873                 :            :         seccomp_policy_builder.AllowFileSystem();
#     874                 :            :         seccomp_policy_builder.AllowNetwork();
#     875                 :            :         break;
#     876                 :            :     case SyscallSandboxPolicy::NET_HTTP_SERVER: // Thread: http
#     877                 :            :         seccomp_policy_builder.AllowFileSystem();
#     878                 :            :         seccomp_policy_builder.AllowNetwork();
#     879                 :            :         break;
#     880                 :            :     case SyscallSandboxPolicy::NET_HTTP_SERVER_WORKER: // Thread: httpworker.<N>
#     881                 :            :         seccomp_policy_builder.AllowFileSystem();
#     882                 :            :         seccomp_policy_builder.AllowNetwork();
#     883                 :            :         break;
#     884                 :            :     case SyscallSandboxPolicy::NET_OPEN_CONNECTION: // Thread: opencon
#     885                 :            :         seccomp_policy_builder.AllowFileSystem();
#     886                 :            :         seccomp_policy_builder.AllowNetwork();
#     887                 :            :         break;
#     888                 :            :     case SyscallSandboxPolicy::SCHEDULER: // Thread: scheduler
#     889                 :            :         seccomp_policy_builder.AllowFileSystem();
#     890                 :            :         break;
#     891                 :            :     case SyscallSandboxPolicy::TOR_CONTROL: // Thread: torcontrol
#     892                 :            :         seccomp_policy_builder.AllowFileSystem();
#     893                 :            :         seccomp_policy_builder.AllowNetwork();
#     894                 :            :         break;
#     895                 :            :     case SyscallSandboxPolicy::TX_INDEX: // Thread: txindex
#     896                 :            :         seccomp_policy_builder.AllowFileSystem();
#     897                 :            :         break;
#     898                 :            :     case SyscallSandboxPolicy::VALIDATION_SCRIPT_CHECK: // Thread: scriptch.<N>
#     899                 :            :         break;
#     900                 :            :     case SyscallSandboxPolicy::SHUTOFF: // Thread: main thread (state: shutoff)
#     901                 :            :         seccomp_policy_builder.AllowFileSystem();
#     902                 :            :         break;
#     903                 :            :     }
#     904                 :            : 
#     905                 :            :     const SyscallSandboxAction default_action = g_syscall_sandbox_log_violation_before_terminating ? SyscallSandboxAction::INVOKE_SIGNAL_HANDLER : SyscallSandboxAction::KILL_PROCESS;
#     906                 :            :     std::vector<sock_filter> filter = seccomp_policy_builder.BuildFilter(default_action);
#     907                 :            :     const sock_fprog prog = {
#     908                 :            :         .len = static_cast<uint16_t>(filter.size()),
#     909                 :            :         .filter = filter.data(),
#     910                 :            :     };
#     911                 :            :     // Do not allow abilities to be regained after being dropped.
#     912                 :            :     //
#     913                 :            :     // PR_SET_NO_NEW_PRIVS documentation: <https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html>
#     914                 :            :     if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
#     915                 :            :         throw std::runtime_error("Syscall sandbox enforcement failed: prctl(PR_SET_NO_NEW_PRIVS)");
#     916                 :            :     }
#     917                 :            :     // Install seccomp-bpf syscall filter.
#     918                 :            :     //
#     919                 :            :     // PR_SET_SECCOMP documentation: <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
#     920                 :            :     if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0) {
#     921                 :            :         throw std::runtime_error("Syscall sandbox enforcement failed: prctl(PR_SET_SECCOMP)");
#     922                 :            :     }
#     923                 :            : 
#     924                 :            :     const std::string thread_name = !util::ThreadGetInternalName().empty() ? util::ThreadGetInternalName() : "*unnamed*";
#     925                 :            :     LogPrint(BCLog::UTIL, "Syscall filter installed for thread \"%s\"\n", thread_name);
#     926                 :            : #endif // defined(USE_SYSCALL_SANDBOX)
#     927                 :      14711 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a