diff options
-rwxr-xr-x | maintainers/check-syscalls.sh | 2 | ||||
-rw-r--r-- | package.nix | 2 | ||||
-rw-r--r-- | src/libstore/build/derivation-goal.cc | 4 | ||||
-rw-r--r-- | src/libstore/build/derivation-goal.hh | 2 | ||||
-rw-r--r-- | src/libstore/build/goal.cc | 27 | ||||
-rw-r--r-- | src/libstore/build/goal.hh | 2 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.cc | 601 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.hh | 6 | ||||
-rw-r--r-- | src/libstore/build/worker.cc | 22 | ||||
-rw-r--r-- | src/libstore/platform/linux.cc | 633 | ||||
-rw-r--r-- | src/libstore/platform/linux.hh | 5 |
11 files changed, 671 insertions, 635 deletions
diff --git a/maintainers/check-syscalls.sh b/maintainers/check-syscalls.sh index cd72ac23b..72b629438 100755 --- a/maintainers/check-syscalls.sh +++ b/maintainers/check-syscalls.sh @@ -2,6 +2,6 @@ set -e -diff -u <(awk < src/libstore/build/local-derivation-goal.cc '/BEGIN extract-syscalls/ { extracting = 1; next } +diff -u <(awk < src/libstore/platform/linux.cc '/BEGIN extract-syscalls/ { extracting = 1; next } match($0, /allowSyscall\(ctx, SCMP_SYS\(([^)]*)\)\);|\/\/ skip ([^ ]*)/, result) { print result[1] result[2] } /END extract-syscalls/ { extracting = 0; next }') <(tail -n+2 "$1" | cut -d, -f 1) diff --git a/package.nix b/package.nix index 7ebe2721b..0f006fef4 100644 --- a/package.nix +++ b/package.nix @@ -502,7 +502,7 @@ stdenv.mkDerivation (finalAttrs: { PATH=$prefix/bin''${PATH:+:''${PATH}} unset PYTHONPATH - export MANPATH=$out/share/man''${MANPATH:+:''${MANPATH}} + export MANPATH=$out/share/man:''${MANPATH:-} # Make bash completion work. XDG_DATA_DIRS+=:$out/share diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index ab7b2b88c..17a2b04f1 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -1541,10 +1541,8 @@ Goal::Finished DerivationGoal::done( } -void DerivationGoal::waiteeDone(GoalPtr waitee, ExitCode result) +void DerivationGoal::waiteeDone(GoalPtr waitee) { - Goal::waiteeDone(waitee, result); - if (!useDerivation) return; auto * dg = dynamic_cast<DerivationGoal *>(&*waitee); diff --git a/src/libstore/build/derivation-goal.hh b/src/libstore/build/derivation-goal.hh index 268b717dd..c43e2aed5 100644 --- a/src/libstore/build/derivation-goal.hh +++ b/src/libstore/build/derivation-goal.hh @@ -332,7 +332,7 @@ struct DerivationGoal : public Goal SingleDrvOutputs builtOutputs = {}, std::optional<Error> ex = {}); - void waiteeDone(GoalPtr waitee, ExitCode result) override; + void waiteeDone(GoalPtr waitee) override; StorePathSet exportReferences(const StorePathSet & storePaths); diff --git a/src/libstore/build/goal.cc b/src/libstore/build/goal.cc index 40a3bae8d..f26c2c671 100644 --- a/src/libstore/build/goal.cc +++ b/src/libstore/build/goal.cc @@ -18,33 +18,6 @@ void Goal::addWaitee(GoalPtr waitee) } -void Goal::waiteeDone(GoalPtr waitee, ExitCode result) -{ - assert(waitees.count(waitee)); - waitees.erase(waitee); - - trace(fmt("waitee '%s' done; %d left", waitee->name, waitees.size())); - - if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed; - - if (result == ecNoSubstituters) ++nrNoSubstituters; - - if (result == ecIncompleteClosure) ++nrIncompleteClosure; - - if (waitees.empty() || (result == ecFailed && !settings.keepGoing)) { - - /* If we failed and keepGoing is not set, we remove all - remaining waitees. */ - for (auto & goal : waitees) { - goal->waiters.extract(shared_from_this()); - } - waitees.clear(); - - worker.wakeUp(shared_from_this()); - } -} - - void Goal::trace(std::string_view s) { debug("%1%: %2%", name, s); diff --git a/src/libstore/build/goal.hh b/src/libstore/build/goal.hh index adb3ab94b..dd29b9fc4 100644 --- a/src/libstore/build/goal.hh +++ b/src/libstore/build/goal.hh @@ -135,7 +135,7 @@ public: void addWaitee(GoalPtr waitee); - virtual void waiteeDone(GoalPtr waitee, ExitCode result); + virtual void waiteeDone(GoalPtr waitee) { } virtual WorkResult handleChildOutput(int fd, std::string_view data) { diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index fb5ccc6f1..23903117a 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -42,11 +42,7 @@ #include <sched.h> #include <sys/param.h> #include <sys/mount.h> -#include <sys/prctl.h> #include <sys/syscall.h> -#if HAVE_SECCOMP -#include <seccomp.h> -#endif #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) #endif @@ -61,14 +57,6 @@ extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, namespace nix { -namespace { -/** - * The system for which Nix is compiled. - */ -[[gnu::unused]] -constexpr const std::string_view nativeSystem = SYSTEM; -} - void handleDiffHook( uid_t uid, uid_t gid, const Path & tryA, const Path & tryB, @@ -1361,593 +1349,6 @@ void LocalDerivationGoal::chownToBuilder(const Path & path) throw SysError("cannot change ownership of '%1%'", path); } -#if HAVE_SECCOMP - -static void allowSyscall(scmp_filter_ctx ctx, int syscall) { - if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 0) != 0) - throw SysError("unable to add seccomp rule"); -} - -#define ALLOW_CHMOD_IF_SAFE(ctx, syscall, modePos) \ - if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISUID | S_ISGID, 0)) != 0 || \ - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISUID, S_ISUID)) != 0 || \ - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISGID, S_ISGID)) != 0) \ - throw SysError("unable to add seccomp rule"); - -#endif - -void setupSeccomp() -{ -#if __linux__ -#if HAVE_SECCOMP - scmp_filter_ctx ctx; - - // Pretend that syscalls we don't yet know about don't exist. - // This is the best option for compatibility: after all, they did in fact not exist not too long ago. - if (!(ctx = seccomp_init(SCMP_ACT_ERRNO(ENOSYS)))) - throw SysError("unable to initialize seccomp mode 2"); - - Finally cleanup([&]() { - seccomp_release(ctx); - }); - - if (nativeSystem == "x86_64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) - throw SysError("unable to add 32-bit seccomp architecture"); - - if (nativeSystem == "x86_64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) - throw SysError("unable to add X32 seccomp architecture"); - - if (nativeSystem == "aarch64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) - printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); - - if (nativeSystem == "mips64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPS) != 0) - printError("unable to add mips seccomp architecture"); - - if (nativeSystem == "mips64-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPS64N32) != 0) - printError("unable to add mips64-*abin32 seccomp architecture"); - - if (nativeSystem == "mips64el-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL) != 0) - printError("unable to add mipsel seccomp architecture"); - - if (nativeSystem == "mips64el-linux" && - seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0) - printError("unable to add mips64el-*abin32 seccomp architecture"); - - // This list is intended for machine consumption. - // Please keep its format, order and BEGIN/END markers. - // - // Currently, it is up to date with libseccomp 2.5.5 and glibc 2.39. - // Run check-syscalls to determine which new syscalls should be added. - // New syscalls must be audited and handled in a way that blocks the following dangerous operations: - // * Creation of non-empty setuid/setgid files - // * Creation of extended attributes (including ACLs) - // - // BEGIN extract-syscalls - allowSyscall(ctx, SCMP_SYS(accept)); - allowSyscall(ctx, SCMP_SYS(accept4)); - allowSyscall(ctx, SCMP_SYS(access)); - allowSyscall(ctx, SCMP_SYS(acct)); - allowSyscall(ctx, SCMP_SYS(add_key)); - allowSyscall(ctx, SCMP_SYS(adjtimex)); - allowSyscall(ctx, SCMP_SYS(afs_syscall)); - allowSyscall(ctx, SCMP_SYS(alarm)); - allowSyscall(ctx, SCMP_SYS(arch_prctl)); - allowSyscall(ctx, SCMP_SYS(arm_fadvise64_64)); - allowSyscall(ctx, SCMP_SYS(arm_sync_file_range)); - allowSyscall(ctx, SCMP_SYS(bdflush)); - allowSyscall(ctx, SCMP_SYS(bind)); - allowSyscall(ctx, SCMP_SYS(bpf)); - allowSyscall(ctx, SCMP_SYS(break)); - allowSyscall(ctx, SCMP_SYS(breakpoint)); - allowSyscall(ctx, SCMP_SYS(brk)); - allowSyscall(ctx, SCMP_SYS(cachectl)); - allowSyscall(ctx, SCMP_SYS(cacheflush)); - allowSyscall(ctx, SCMP_SYS(cachestat)); - allowSyscall(ctx, SCMP_SYS(capget)); - allowSyscall(ctx, SCMP_SYS(capset)); - allowSyscall(ctx, SCMP_SYS(chdir)); - // skip chmod (dangerous) - allowSyscall(ctx, SCMP_SYS(chown)); - allowSyscall(ctx, SCMP_SYS(chown32)); - allowSyscall(ctx, SCMP_SYS(chroot)); - allowSyscall(ctx, SCMP_SYS(clock_adjtime)); - allowSyscall(ctx, SCMP_SYS(clock_adjtime64)); - allowSyscall(ctx, SCMP_SYS(clock_getres)); - allowSyscall(ctx, SCMP_SYS(clock_getres_time64)); - allowSyscall(ctx, SCMP_SYS(clock_gettime)); - allowSyscall(ctx, SCMP_SYS(clock_gettime64)); - allowSyscall(ctx, SCMP_SYS(clock_nanosleep)); - allowSyscall(ctx, SCMP_SYS(clock_nanosleep_time64)); - allowSyscall(ctx, SCMP_SYS(clock_settime)); - allowSyscall(ctx, SCMP_SYS(clock_settime64)); - allowSyscall(ctx, SCMP_SYS(clone)); - allowSyscall(ctx, SCMP_SYS(clone3)); - allowSyscall(ctx, SCMP_SYS(close)); - allowSyscall(ctx, SCMP_SYS(close_range)); - allowSyscall(ctx, SCMP_SYS(connect)); - allowSyscall(ctx, SCMP_SYS(copy_file_range)); - allowSyscall(ctx, SCMP_SYS(creat)); - allowSyscall(ctx, SCMP_SYS(create_module)); - allowSyscall(ctx, SCMP_SYS(delete_module)); - allowSyscall(ctx, SCMP_SYS(dup)); - allowSyscall(ctx, SCMP_SYS(dup2)); - allowSyscall(ctx, SCMP_SYS(dup3)); - allowSyscall(ctx, SCMP_SYS(epoll_create)); - allowSyscall(ctx, SCMP_SYS(epoll_create1)); - allowSyscall(ctx, SCMP_SYS(epoll_ctl)); - allowSyscall(ctx, SCMP_SYS(epoll_ctl_old)); - allowSyscall(ctx, SCMP_SYS(epoll_pwait)); - allowSyscall(ctx, SCMP_SYS(epoll_pwait2)); - allowSyscall(ctx, SCMP_SYS(epoll_wait)); - allowSyscall(ctx, SCMP_SYS(epoll_wait_old)); - allowSyscall(ctx, SCMP_SYS(eventfd)); - allowSyscall(ctx, SCMP_SYS(eventfd2)); - allowSyscall(ctx, SCMP_SYS(execve)); - allowSyscall(ctx, SCMP_SYS(execveat)); - allowSyscall(ctx, SCMP_SYS(exit)); - allowSyscall(ctx, SCMP_SYS(exit_group)); - allowSyscall(ctx, SCMP_SYS(faccessat)); - allowSyscall(ctx, SCMP_SYS(faccessat2)); - allowSyscall(ctx, SCMP_SYS(fadvise64)); - allowSyscall(ctx, SCMP_SYS(fadvise64_64)); - allowSyscall(ctx, SCMP_SYS(fallocate)); - allowSyscall(ctx, SCMP_SYS(fanotify_init)); - allowSyscall(ctx, SCMP_SYS(fanotify_mark)); - allowSyscall(ctx, SCMP_SYS(fchdir)); - // skip fchmod (dangerous) - // skip fchmodat (dangerous) - // skip fchmodat2 (dangerous) - allowSyscall(ctx, SCMP_SYS(fchown)); - allowSyscall(ctx, SCMP_SYS(fchown32)); - allowSyscall(ctx, SCMP_SYS(fchownat)); - allowSyscall(ctx, SCMP_SYS(fcntl)); - allowSyscall(ctx, SCMP_SYS(fcntl64)); - allowSyscall(ctx, SCMP_SYS(fdatasync)); - allowSyscall(ctx, SCMP_SYS(fgetxattr)); - allowSyscall(ctx, SCMP_SYS(finit_module)); - allowSyscall(ctx, SCMP_SYS(flistxattr)); - allowSyscall(ctx, SCMP_SYS(flock)); - allowSyscall(ctx, SCMP_SYS(fork)); - allowSyscall(ctx, SCMP_SYS(fremovexattr)); - allowSyscall(ctx, SCMP_SYS(fsconfig)); - // skip fsetxattr (dangerous) - allowSyscall(ctx, SCMP_SYS(fsmount)); - allowSyscall(ctx, SCMP_SYS(fsopen)); - allowSyscall(ctx, SCMP_SYS(fspick)); - allowSyscall(ctx, SCMP_SYS(fstat)); - allowSyscall(ctx, SCMP_SYS(fstat64)); - allowSyscall(ctx, SCMP_SYS(fstatat64)); - allowSyscall(ctx, SCMP_SYS(fstatfs)); - allowSyscall(ctx, SCMP_SYS(fstatfs64)); - allowSyscall(ctx, SCMP_SYS(fsync)); - allowSyscall(ctx, SCMP_SYS(ftime)); - allowSyscall(ctx, SCMP_SYS(ftruncate)); - allowSyscall(ctx, SCMP_SYS(ftruncate64)); - allowSyscall(ctx, SCMP_SYS(futex)); - allowSyscall(ctx, SCMP_SYS(futex_requeue)); - allowSyscall(ctx, SCMP_SYS(futex_time64)); - allowSyscall(ctx, SCMP_SYS(futex_wait)); - allowSyscall(ctx, SCMP_SYS(futex_waitv)); - allowSyscall(ctx, SCMP_SYS(futex_wake)); - allowSyscall(ctx, SCMP_SYS(futimesat)); - allowSyscall(ctx, SCMP_SYS(getcpu)); - allowSyscall(ctx, SCMP_SYS(getcwd)); - allowSyscall(ctx, SCMP_SYS(getdents)); - allowSyscall(ctx, SCMP_SYS(getdents64)); - allowSyscall(ctx, SCMP_SYS(getegid)); - allowSyscall(ctx, SCMP_SYS(getegid32)); - allowSyscall(ctx, SCMP_SYS(geteuid)); - allowSyscall(ctx, SCMP_SYS(geteuid32)); - allowSyscall(ctx, SCMP_SYS(getgid)); - allowSyscall(ctx, SCMP_SYS(getgid32)); - allowSyscall(ctx, SCMP_SYS(getgroups)); - allowSyscall(ctx, SCMP_SYS(getgroups32)); - allowSyscall(ctx, SCMP_SYS(getitimer)); - allowSyscall(ctx, SCMP_SYS(get_kernel_syms)); - allowSyscall(ctx, SCMP_SYS(get_mempolicy)); - allowSyscall(ctx, SCMP_SYS(getpeername)); - allowSyscall(ctx, SCMP_SYS(getpgid)); - allowSyscall(ctx, SCMP_SYS(getpgrp)); - allowSyscall(ctx, SCMP_SYS(getpid)); - allowSyscall(ctx, SCMP_SYS(getpmsg)); - allowSyscall(ctx, SCMP_SYS(getppid)); - allowSyscall(ctx, SCMP_SYS(getpriority)); - allowSyscall(ctx, SCMP_SYS(getrandom)); - allowSyscall(ctx, SCMP_SYS(getresgid)); - allowSyscall(ctx, SCMP_SYS(getresgid32)); - allowSyscall(ctx, SCMP_SYS(getresuid)); - allowSyscall(ctx, SCMP_SYS(getresuid32)); - allowSyscall(ctx, SCMP_SYS(getrlimit)); - allowSyscall(ctx, SCMP_SYS(get_robust_list)); - allowSyscall(ctx, SCMP_SYS(getrusage)); - allowSyscall(ctx, SCMP_SYS(getsid)); - allowSyscall(ctx, SCMP_SYS(getsockname)); - allowSyscall(ctx, SCMP_SYS(getsockopt)); - allowSyscall(ctx, SCMP_SYS(get_thread_area)); - allowSyscall(ctx, SCMP_SYS(gettid)); - allowSyscall(ctx, SCMP_SYS(gettimeofday)); - allowSyscall(ctx, SCMP_SYS(get_tls)); - allowSyscall(ctx, SCMP_SYS(getuid)); - allowSyscall(ctx, SCMP_SYS(getuid32)); - allowSyscall(ctx, SCMP_SYS(getxattr)); - allowSyscall(ctx, SCMP_SYS(gtty)); - allowSyscall(ctx, SCMP_SYS(idle)); - allowSyscall(ctx, SCMP_SYS(init_module)); - allowSyscall(ctx, SCMP_SYS(inotify_add_watch)); - allowSyscall(ctx, SCMP_SYS(inotify_init)); - allowSyscall(ctx, SCMP_SYS(inotify_init1)); - allowSyscall(ctx, SCMP_SYS(inotify_rm_watch)); - allowSyscall(ctx, SCMP_SYS(io_cancel)); - allowSyscall(ctx, SCMP_SYS(ioctl)); - allowSyscall(ctx, SCMP_SYS(io_destroy)); - allowSyscall(ctx, SCMP_SYS(io_getevents)); - allowSyscall(ctx, SCMP_SYS(ioperm)); - allowSyscall(ctx, SCMP_SYS(io_pgetevents)); - allowSyscall(ctx, SCMP_SYS(io_pgetevents_time64)); - allowSyscall(ctx, SCMP_SYS(iopl)); - allowSyscall(ctx, SCMP_SYS(ioprio_get)); - allowSyscall(ctx, SCMP_SYS(ioprio_set)); - allowSyscall(ctx, SCMP_SYS(io_setup)); - allowSyscall(ctx, SCMP_SYS(io_submit)); - // skip io_uring_enter (may become dangerous) - // skip io_uring_register (may become dangerous) - // skip io_uring_setup (may become dangerous) - allowSyscall(ctx, SCMP_SYS(ipc)); - allowSyscall(ctx, SCMP_SYS(kcmp)); - allowSyscall(ctx, SCMP_SYS(kexec_file_load)); - allowSyscall(ctx, SCMP_SYS(kexec_load)); - allowSyscall(ctx, SCMP_SYS(keyctl)); - allowSyscall(ctx, SCMP_SYS(kill)); - allowSyscall(ctx, SCMP_SYS(landlock_add_rule)); - allowSyscall(ctx, SCMP_SYS(landlock_create_ruleset)); - allowSyscall(ctx, SCMP_SYS(landlock_restrict_self)); - allowSyscall(ctx, SCMP_SYS(lchown)); - allowSyscall(ctx, SCMP_SYS(lchown32)); - allowSyscall(ctx, SCMP_SYS(lgetxattr)); - allowSyscall(ctx, SCMP_SYS(link)); - allowSyscall(ctx, SCMP_SYS(linkat)); - allowSyscall(ctx, SCMP_SYS(listen)); - allowSyscall(ctx, SCMP_SYS(listxattr)); - allowSyscall(ctx, SCMP_SYS(llistxattr)); - allowSyscall(ctx, SCMP_SYS(_llseek)); - allowSyscall(ctx, SCMP_SYS(lock)); - allowSyscall(ctx, SCMP_SYS(lookup_dcookie)); - allowSyscall(ctx, SCMP_SYS(lremovexattr)); - allowSyscall(ctx, SCMP_SYS(lseek)); - // skip lsetxattr (dangerous) - allowSyscall(ctx, SCMP_SYS(lstat)); - allowSyscall(ctx, SCMP_SYS(lstat64)); - allowSyscall(ctx, SCMP_SYS(madvise)); - allowSyscall(ctx, SCMP_SYS(map_shadow_stack)); - allowSyscall(ctx, SCMP_SYS(mbind)); - allowSyscall(ctx, SCMP_SYS(membarrier)); - allowSyscall(ctx, SCMP_SYS(memfd_create)); - allowSyscall(ctx, SCMP_SYS(memfd_secret)); - allowSyscall(ctx, SCMP_SYS(migrate_pages)); - allowSyscall(ctx, SCMP_SYS(mincore)); - allowSyscall(ctx, SCMP_SYS(mkdir)); - allowSyscall(ctx, SCMP_SYS(mkdirat)); - allowSyscall(ctx, SCMP_SYS(mknod)); - allowSyscall(ctx, SCMP_SYS(mknodat)); - allowSyscall(ctx, SCMP_SYS(mlock)); - allowSyscall(ctx, SCMP_SYS(mlock2)); - allowSyscall(ctx, SCMP_SYS(mlockall)); - allowSyscall(ctx, SCMP_SYS(mmap)); - allowSyscall(ctx, SCMP_SYS(mmap2)); - allowSyscall(ctx, SCMP_SYS(modify_ldt)); - allowSyscall(ctx, SCMP_SYS(mount)); - allowSyscall(ctx, SCMP_SYS(mount_setattr)); - allowSyscall(ctx, SCMP_SYS(move_mount)); - allowSyscall(ctx, SCMP_SYS(move_pages)); - allowSyscall(ctx, SCMP_SYS(mprotect)); - allowSyscall(ctx, SCMP_SYS(mpx)); - allowSyscall(ctx, SCMP_SYS(mq_getsetattr)); - allowSyscall(ctx, SCMP_SYS(mq_notify)); - allowSyscall(ctx, SCMP_SYS(mq_open)); - allowSyscall(ctx, SCMP_SYS(mq_timedreceive)); - allowSyscall(ctx, SCMP_SYS(mq_timedreceive_time64)); - allowSyscall(ctx, SCMP_SYS(mq_timedsend)); - allowSyscall(ctx, SCMP_SYS(mq_timedsend_time64)); - allowSyscall(ctx, SCMP_SYS(mq_unlink)); - allowSyscall(ctx, SCMP_SYS(mremap)); - allowSyscall(ctx, SCMP_SYS(msgctl)); - allowSyscall(ctx, SCMP_SYS(msgget)); - allowSyscall(ctx, SCMP_SYS(msgrcv)); - allowSyscall(ctx, SCMP_SYS(msgsnd)); - allowSyscall(ctx, SCMP_SYS(msync)); - allowSyscall(ctx, SCMP_SYS(multiplexer)); - allowSyscall(ctx, SCMP_SYS(munlock)); - allowSyscall(ctx, SCMP_SYS(munlockall)); - allowSyscall(ctx, SCMP_SYS(munmap)); - allowSyscall(ctx, SCMP_SYS(name_to_handle_at)); - allowSyscall(ctx, SCMP_SYS(nanosleep)); - allowSyscall(ctx, SCMP_SYS(newfstatat)); - allowSyscall(ctx, SCMP_SYS(_newselect)); - allowSyscall(ctx, SCMP_SYS(nfsservctl)); - allowSyscall(ctx, SCMP_SYS(nice)); - allowSyscall(ctx, SCMP_SYS(oldfstat)); - allowSyscall(ctx, SCMP_SYS(oldlstat)); - allowSyscall(ctx, SCMP_SYS(oldolduname)); - allowSyscall(ctx, SCMP_SYS(oldstat)); - allowSyscall(ctx, SCMP_SYS(olduname)); - allowSyscall(ctx, SCMP_SYS(open)); - allowSyscall(ctx, SCMP_SYS(openat)); - allowSyscall(ctx, SCMP_SYS(openat2)); - allowSyscall(ctx, SCMP_SYS(open_by_handle_at)); - allowSyscall(ctx, SCMP_SYS(open_tree)); - allowSyscall(ctx, SCMP_SYS(pause)); - allowSyscall(ctx, SCMP_SYS(pciconfig_iobase)); - allowSyscall(ctx, SCMP_SYS(pciconfig_read)); - allowSyscall(ctx, SCMP_SYS(pciconfig_write)); - allowSyscall(ctx, SCMP_SYS(perf_event_open)); - allowSyscall(ctx, SCMP_SYS(personality)); - allowSyscall(ctx, SCMP_SYS(pidfd_getfd)); - allowSyscall(ctx, SCMP_SYS(pidfd_open)); - allowSyscall(ctx, SCMP_SYS(pidfd_send_signal)); - allowSyscall(ctx, SCMP_SYS(pipe)); - allowSyscall(ctx, SCMP_SYS(pipe2)); - allowSyscall(ctx, SCMP_SYS(pivot_root)); - allowSyscall(ctx, SCMP_SYS(pkey_alloc)); - allowSyscall(ctx, SCMP_SYS(pkey_free)); - allowSyscall(ctx, SCMP_SYS(pkey_mprotect)); - allowSyscall(ctx, SCMP_SYS(poll)); - allowSyscall(ctx, SCMP_SYS(ppoll)); - allowSyscall(ctx, SCMP_SYS(ppoll_time64)); - allowSyscall(ctx, SCMP_SYS(prctl)); - allowSyscall(ctx, SCMP_SYS(pread64)); - allowSyscall(ctx, SCMP_SYS(preadv)); - allowSyscall(ctx, SCMP_SYS(preadv2)); - allowSyscall(ctx, SCMP_SYS(prlimit64)); - allowSyscall(ctx, SCMP_SYS(process_madvise)); - allowSyscall(ctx, SCMP_SYS(process_mrelease)); - allowSyscall(ctx, SCMP_SYS(process_vm_readv)); - allowSyscall(ctx, SCMP_SYS(process_vm_writev)); - allowSyscall(ctx, SCMP_SYS(prof)); - allowSyscall(ctx, SCMP_SYS(profil)); - allowSyscall(ctx, SCMP_SYS(pselect6)); - allowSyscall(ctx, SCMP_SYS(pselect6_time64)); - allowSyscall(ctx, SCMP_SYS(ptrace)); - allowSyscall(ctx, SCMP_SYS(putpmsg)); - allowSyscall(ctx, SCMP_SYS(pwrite64)); - allowSyscall(ctx, SCMP_SYS(pwritev)); - allowSyscall(ctx, SCMP_SYS(pwritev2)); - allowSyscall(ctx, SCMP_SYS(query_module)); - allowSyscall(ctx, SCMP_SYS(quotactl)); - allowSyscall(ctx, SCMP_SYS(quotactl_fd)); - allowSyscall(ctx, SCMP_SYS(read)); - allowSyscall(ctx, SCMP_SYS(readahead)); - allowSyscall(ctx, SCMP_SYS(readdir)); - allowSyscall(ctx, SCMP_SYS(readlink)); - allowSyscall(ctx, SCMP_SYS(readlinkat)); - allowSyscall(ctx, SCMP_SYS(readv)); - allowSyscall(ctx, SCMP_SYS(reboot)); - allowSyscall(ctx, SCMP_SYS(recv)); - allowSyscall(ctx, SCMP_SYS(recvfrom)); - allowSyscall(ctx, SCMP_SYS(recvmmsg)); - allowSyscall(ctx, SCMP_SYS(recvmmsg_time64)); - allowSyscall(ctx, SCMP_SYS(recvmsg)); - allowSyscall(ctx, SCMP_SYS(remap_file_pages)); - allowSyscall(ctx, SCMP_SYS(removexattr)); - allowSyscall(ctx, SCMP_SYS(rename)); - allowSyscall(ctx, SCMP_SYS(renameat)); - allowSyscall(ctx, SCMP_SYS(renameat2)); - allowSyscall(ctx, SCMP_SYS(request_key)); - allowSyscall(ctx, SCMP_SYS(restart_syscall)); - allowSyscall(ctx, SCMP_SYS(riscv_flush_icache)); - allowSyscall(ctx, SCMP_SYS(rmdir)); - allowSyscall(ctx, SCMP_SYS(rseq)); - allowSyscall(ctx, SCMP_SYS(rtas)); - allowSyscall(ctx, SCMP_SYS(rt_sigaction)); - allowSyscall(ctx, SCMP_SYS(rt_sigpending)); - allowSyscall(ctx, SCMP_SYS(rt_sigprocmask)); - allowSyscall(ctx, SCMP_SYS(rt_sigqueueinfo)); - allowSyscall(ctx, SCMP_SYS(rt_sigreturn)); - allowSyscall(ctx, SCMP_SYS(rt_sigsuspend)); - allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait)); - allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait_time64)); - allowSyscall(ctx, SCMP_SYS(rt_tgsigqueueinfo)); - allowSyscall(ctx, SCMP_SYS(s390_guarded_storage)); - allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_read)); - allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_write)); - allowSyscall(ctx, SCMP_SYS(s390_runtime_instr)); - allowSyscall(ctx, SCMP_SYS(s390_sthyi)); - allowSyscall(ctx, SCMP_SYS(sched_getaffinity)); - allowSyscall(ctx, SCMP_SYS(sched_getattr)); - allowSyscall(ctx, SCMP_SYS(sched_getparam)); - allowSyscall(ctx, SCMP_SYS(sched_get_priority_max)); - allowSyscall(ctx, SCMP_SYS(sched_get_priority_min)); - allowSyscall(ctx, SCMP_SYS(sched_getscheduler)); - allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval)); - allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval_time64)); - allowSyscall(ctx, SCMP_SYS(sched_setaffinity)); - allowSyscall(ctx, SCMP_SYS(sched_setattr)); - allowSyscall(ctx, SCMP_SYS(sched_setparam)); - allowSyscall(ctx, SCMP_SYS(sched_setscheduler)); - allowSyscall(ctx, SCMP_SYS(sched_yield)); - allowSyscall(ctx, SCMP_SYS(seccomp)); - allowSyscall(ctx, SCMP_SYS(security)); - allowSyscall(ctx, SCMP_SYS(select)); - allowSyscall(ctx, SCMP_SYS(semctl)); - allowSyscall(ctx, SCMP_SYS(semget)); - allowSyscall(ctx, SCMP_SYS(semop)); - allowSyscall(ctx, SCMP_SYS(semtimedop)); - allowSyscall(ctx, SCMP_SYS(semtimedop_time64)); - allowSyscall(ctx, SCMP_SYS(send)); - allowSyscall(ctx, SCMP_SYS(sendfile)); - allowSyscall(ctx, SCMP_SYS(sendfile64)); - allowSyscall(ctx, SCMP_SYS(sendmmsg)); - allowSyscall(ctx, SCMP_SYS(sendmsg)); - allowSyscall(ctx, SCMP_SYS(sendto)); - allowSyscall(ctx, SCMP_SYS(setdomainname)); - allowSyscall(ctx, SCMP_SYS(setfsgid)); - allowSyscall(ctx, SCMP_SYS(setfsgid32)); - allowSyscall(ctx, SCMP_SYS(setfsuid)); - allowSyscall(ctx, SCMP_SYS(setfsuid32)); - allowSyscall(ctx, SCMP_SYS(setgid)); - allowSyscall(ctx, SCMP_SYS(setgid32)); - allowSyscall(ctx, SCMP_SYS(setgroups)); - allowSyscall(ctx, SCMP_SYS(setgroups32)); - allowSyscall(ctx, SCMP_SYS(sethostname)); - allowSyscall(ctx, SCMP_SYS(setitimer)); - allowSyscall(ctx, SCMP_SYS(set_mempolicy)); - allowSyscall(ctx, SCMP_SYS(set_mempolicy_home_node)); - allowSyscall(ctx, SCMP_SYS(setns)); - allowSyscall(ctx, SCMP_SYS(setpgid)); - allowSyscall(ctx, SCMP_SYS(setpriority)); - allowSyscall(ctx, SCMP_SYS(setregid)); - allowSyscall(ctx, SCMP_SYS(setregid32)); - allowSyscall(ctx, SCMP_SYS(setresgid)); - allowSyscall(ctx, SCMP_SYS(setresgid32)); - allowSyscall(ctx, SCMP_SYS(setresuid)); - allowSyscall(ctx, SCMP_SYS(setresuid32)); - allowSyscall(ctx, SCMP_SYS(setreuid)); - allowSyscall(ctx, SCMP_SYS(setreuid32)); - allowSyscall(ctx, SCMP_SYS(setrlimit)); - allowSyscall(ctx, SCMP_SYS(set_robust_list)); - allowSyscall(ctx, SCMP_SYS(setsid)); - allowSyscall(ctx, SCMP_SYS(setsockopt)); - allowSyscall(ctx, SCMP_SYS(set_thread_area)); - allowSyscall(ctx, SCMP_SYS(set_tid_address)); - allowSyscall(ctx, SCMP_SYS(settimeofday)); - allowSyscall(ctx, SCMP_SYS(set_tls)); - allowSyscall(ctx, SCMP_SYS(setuid)); - allowSyscall(ctx, SCMP_SYS(setuid32)); - // skip setxattr (dangerous) - allowSyscall(ctx, SCMP_SYS(sgetmask)); - allowSyscall(ctx, SCMP_SYS(shmat)); - allowSyscall(ctx, SCMP_SYS(shmctl)); - allowSyscall(ctx, SCMP_SYS(shmdt)); - allowSyscall(ctx, SCMP_SYS(shmget)); - allowSyscall(ctx, SCMP_SYS(shutdown)); - allowSyscall(ctx, SCMP_SYS(sigaction)); - allowSyscall(ctx, SCMP_SYS(sigaltstack)); - allowSyscall(ctx, SCMP_SYS(signal)); - allowSyscall(ctx, SCMP_SYS(signalfd)); - allowSyscall(ctx, SCMP_SYS(signalfd4)); - allowSyscall(ctx, SCMP_SYS(sigpending)); - allowSyscall(ctx, SCMP_SYS(sigprocmask)); - allowSyscall(ctx, SCMP_SYS(sigreturn)); - allowSyscall(ctx, SCMP_SYS(sigsuspend)); - allowSyscall(ctx, SCMP_SYS(socket)); - allowSyscall(ctx, SCMP_SYS(socketcall)); - allowSyscall(ctx, SCMP_SYS(socketpair)); - allowSyscall(ctx, SCMP_SYS(splice)); - allowSyscall(ctx, SCMP_SYS(spu_create)); - allowSyscall(ctx, SCMP_SYS(spu_run)); - allowSyscall(ctx, SCMP_SYS(ssetmask)); - allowSyscall(ctx, SCMP_SYS(stat)); - allowSyscall(ctx, SCMP_SYS(stat64)); - allowSyscall(ctx, SCMP_SYS(statfs)); - allowSyscall(ctx, SCMP_SYS(statfs64)); - allowSyscall(ctx, SCMP_SYS(statx)); - allowSyscall(ctx, SCMP_SYS(stime)); - allowSyscall(ctx, SCMP_SYS(stty)); - allowSyscall(ctx, SCMP_SYS(subpage_prot)); - allowSyscall(ctx, SCMP_SYS(swapcontext)); - allowSyscall(ctx, SCMP_SYS(swapoff)); - allowSyscall(ctx, SCMP_SYS(swapon)); - allowSyscall(ctx, SCMP_SYS(switch_endian)); - allowSyscall(ctx, SCMP_SYS(symlink)); - allowSyscall(ctx, SCMP_SYS(symlinkat)); - allowSyscall(ctx, SCMP_SYS(sync)); - allowSyscall(ctx, SCMP_SYS(sync_file_range)); - allowSyscall(ctx, SCMP_SYS(sync_file_range2)); - allowSyscall(ctx, SCMP_SYS(syncfs)); - allowSyscall(ctx, SCMP_SYS(syscall)); - allowSyscall(ctx, SCMP_SYS(_sysctl)); - allowSyscall(ctx, SCMP_SYS(sys_debug_setcontext)); - allowSyscall(ctx, SCMP_SYS(sysfs)); - allowSyscall(ctx, SCMP_SYS(sysinfo)); - allowSyscall(ctx, SCMP_SYS(syslog)); - allowSyscall(ctx, SCMP_SYS(sysmips)); - allowSyscall(ctx, SCMP_SYS(tee)); - allowSyscall(ctx, SCMP_SYS(tgkill)); - allowSyscall(ctx, SCMP_SYS(time)); - allowSyscall(ctx, SCMP_SYS(timer_create)); - allowSyscall(ctx, SCMP_SYS(timer_delete)); - allowSyscall(ctx, SCMP_SYS(timerfd)); - allowSyscall(ctx, SCMP_SYS(timerfd_create)); - allowSyscall(ctx, SCMP_SYS(timerfd_gettime)); - allowSyscall(ctx, SCMP_SYS(timerfd_gettime64)); - allowSyscall(ctx, SCMP_SYS(timerfd_settime)); - allowSyscall(ctx, SCMP_SYS(timerfd_settime64)); - allowSyscall(ctx, SCMP_SYS(timer_getoverrun)); - allowSyscall(ctx, SCMP_SYS(timer_gettime)); - allowSyscall(ctx, SCMP_SYS(timer_gettime64)); - allowSyscall(ctx, SCMP_SYS(timer_settime)); - allowSyscall(ctx, SCMP_SYS(timer_settime64)); - allowSyscall(ctx, SCMP_SYS(times)); - allowSyscall(ctx, SCMP_SYS(tkill)); - allowSyscall(ctx, SCMP_SYS(truncate)); - allowSyscall(ctx, SCMP_SYS(truncate64)); - allowSyscall(ctx, SCMP_SYS(tuxcall)); - allowSyscall(ctx, SCMP_SYS(ugetrlimit)); - allowSyscall(ctx, SCMP_SYS(ulimit)); - allowSyscall(ctx, SCMP_SYS(umask)); - allowSyscall(ctx, SCMP_SYS(umount)); - allowSyscall(ctx, SCMP_SYS(umount2)); - allowSyscall(ctx, SCMP_SYS(uname)); - allowSyscall(ctx, SCMP_SYS(unlink)); - allowSyscall(ctx, SCMP_SYS(unlinkat)); - allowSyscall(ctx, SCMP_SYS(unshare)); - allowSyscall(ctx, SCMP_SYS(uselib)); - allowSyscall(ctx, SCMP_SYS(userfaultfd)); - allowSyscall(ctx, SCMP_SYS(usr26)); - allowSyscall(ctx, SCMP_SYS(usr32)); - allowSyscall(ctx, SCMP_SYS(ustat)); - allowSyscall(ctx, SCMP_SYS(utime)); - allowSyscall(ctx, SCMP_SYS(utimensat)); - allowSyscall(ctx, SCMP_SYS(utimensat_time64)); - allowSyscall(ctx, SCMP_SYS(utimes)); - allowSyscall(ctx, SCMP_SYS(vfork)); - allowSyscall(ctx, SCMP_SYS(vhangup)); - allowSyscall(ctx, SCMP_SYS(vm86)); - allowSyscall(ctx, SCMP_SYS(vm86old)); - allowSyscall(ctx, SCMP_SYS(vmsplice)); - allowSyscall(ctx, SCMP_SYS(vserver)); - allowSyscall(ctx, SCMP_SYS(wait4)); - allowSyscall(ctx, SCMP_SYS(waitid)); - allowSyscall(ctx, SCMP_SYS(waitpid)); - allowSyscall(ctx, SCMP_SYS(write)); - allowSyscall(ctx, SCMP_SYS(writev)); - // END extract-syscalls - - // chmod family: prevent adding setuid/setgid bits to existing files. - // The Nix store does not support setuid/setgid, and even their temporary creation can weaken the security of the sandbox. - ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(chmod), 1); - ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmod), 1); - ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat), 2); - ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat2), 2); - - // setxattr family: prevent creation of extended attributes or ACLs. - // Not all filesystems support them, and they're incompatible with the NAR format. - if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 || - seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0) - throw SysError("unable to add seccomp rule"); - - // Set the NO_NEW_PRIVS prctl flag. - // This both makes loading seccomp filters work for unprivileged users, - // and is an additional security measure in its own right. - if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 1) != 0) - throw SysError("unable to set 'no new privileges' seccomp attribute"); - - if (seccomp_load(ctx) != 0) - throw SysError("unable to load seccomp BPF program"); -#else - // Still set the no-new-privileges flag if libseccomp is not available. - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) - throw SysError("PR_SET_NO_NEW_PRIVS failed"); -#endif -#endif -} - void LocalDerivationGoal::runChild() { @@ -1960,7 +1361,7 @@ void LocalDerivationGoal::runChild() commonChildInit(); - setupSeccomp(); + setupSyscallFilter(); bool setUser = true; diff --git a/src/libstore/build/local-derivation-goal.hh b/src/libstore/build/local-derivation-goal.hh index 237417b42..e87f2c696 100644 --- a/src/libstore/build/local-derivation-goal.hh +++ b/src/libstore/build/local-derivation-goal.hh @@ -340,6 +340,12 @@ protected: virtual Pid startChild(std::function<void()> openSlave); /** + * Set up the system call filtering required for the sandbox. + * This currently only has an effect on Linux. + */ + virtual void setupSyscallFilter() {} + + /** * Execute the builder, replacing the current process. * Generally this means an `execve` call. */ diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index f4c352b61..84727a377 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -154,7 +154,27 @@ void Worker::goalFinished(GoalPtr goal, Goal::Finished & f) for (auto & i : goal->waiters) { if (GoalPtr waiting = i.lock()) { - waiting->waiteeDone(goal, f.result); + assert(waiting->waitees.count(goal)); + waiting->waitees.erase(goal); + + waiting->trace(fmt("waitee '%s' done; %d left", goal->name, waiting->waitees.size())); + + if (f.result != Goal::ecSuccess) ++waiting->nrFailed; + if (f.result == Goal::ecNoSubstituters) ++waiting->nrNoSubstituters; + if (f.result == Goal::ecIncompleteClosure) ++waiting->nrIncompleteClosure; + + if (waiting->waitees.empty() || (f.result == Goal::ecFailed && !settings.keepGoing)) { + /* If we failed and keepGoing is not set, we remove all + remaining waitees. */ + for (auto & i : waiting->waitees) { + i->waiters.extract(waiting); + } + waiting->waitees.clear(); + + wakeUp(waiting); + } + + waiting->waiteeDone(goal); } } goal->waiters.clear(); diff --git a/src/libstore/platform/linux.cc b/src/libstore/platform/linux.cc index 204f62b71..03b8bc0be 100644 --- a/src/libstore/platform/linux.cc +++ b/src/libstore/platform/linux.cc @@ -8,8 +8,23 @@ #include <grp.h> #include <regex> +#include <sys/prctl.h> + +#if HAVE_SECCOMP +#include <linux/filter.h> +#include <seccomp.h> +#endif namespace nix { + +namespace { +/** + * The system for which Nix is compiled. + */ +[[gnu::unused]] +constexpr const std::string_view nativeSystem = SYSTEM; +} + static RegisterStoreImplementation<LinuxLocalStore, LocalStoreConfig> regLocalStore; static void readProcLink(const std::string & file, UncheckedRoots & roots) @@ -119,6 +134,617 @@ void LinuxLocalStore::findPlatformRoots(UncheckedRoots & unchecked) readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked); } +#if HAVE_SECCOMP + +static void allowSyscall(scmp_filter_ctx ctx, int syscall) { + if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 0) != 0) + throw SysError("unable to add seccomp rule"); +} + +#define ALLOW_CHMOD_IF_SAFE(ctx, syscall, modePos) \ + if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISUID | S_ISGID, 0)) != 0 || \ + seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISUID, S_ISUID)) != 0 || \ + seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), syscall, 1, SCMP_A##modePos(SCMP_CMP_MASKED_EQ, S_ISGID, S_ISGID)) != 0) \ + throw SysError("unable to add seccomp rule"); + +static std::vector<struct sock_filter> compileSyscallFilter() +{ + scmp_filter_ctx ctx; + + // Pretend that syscalls we don't yet know about don't exist. + // This is the best option for compatibility: after all, they did in fact not exist not too long ago. + if (!(ctx = seccomp_init(SCMP_ACT_ERRNO(ENOSYS)))) + throw SysError("unable to initialize seccomp mode 2"); + + Finally cleanup([&]() { + seccomp_release(ctx); + }); + + if (nativeSystem == "x86_64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) + throw SysError("unable to add 32-bit seccomp architecture"); + + if (nativeSystem == "x86_64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) + throw SysError("unable to add X32 seccomp architecture"); + + if (nativeSystem == "aarch64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) + printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); + + if (nativeSystem == "mips64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_MIPS) != 0) + printError("unable to add mips seccomp architecture"); + + if (nativeSystem == "mips64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_MIPS64N32) != 0) + printError("unable to add mips64-*abin32 seccomp architecture"); + + if (nativeSystem == "mips64el-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL) != 0) + printError("unable to add mipsel seccomp architecture"); + + if (nativeSystem == "mips64el-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32) != 0) + printError("unable to add mips64el-*abin32 seccomp architecture"); + + // This list is intended for machine consumption. + // Please keep its format, order and BEGIN/END markers. + // + // Currently, it is up to date with libseccomp 2.5.5 and glibc 2.39. + // Run check-syscalls to determine which new syscalls should be added. + // New syscalls must be audited and handled in a way that blocks the following dangerous operations: + // * Creation of non-empty setuid/setgid files + // * Creation of extended attributes (including ACLs) + // + // BEGIN extract-syscalls + allowSyscall(ctx, SCMP_SYS(accept)); + allowSyscall(ctx, SCMP_SYS(accept4)); + allowSyscall(ctx, SCMP_SYS(access)); + allowSyscall(ctx, SCMP_SYS(acct)); + allowSyscall(ctx, SCMP_SYS(add_key)); + allowSyscall(ctx, SCMP_SYS(adjtimex)); + allowSyscall(ctx, SCMP_SYS(afs_syscall)); + allowSyscall(ctx, SCMP_SYS(alarm)); + allowSyscall(ctx, SCMP_SYS(arch_prctl)); + allowSyscall(ctx, SCMP_SYS(arm_fadvise64_64)); + allowSyscall(ctx, SCMP_SYS(arm_sync_file_range)); + allowSyscall(ctx, SCMP_SYS(bdflush)); + allowSyscall(ctx, SCMP_SYS(bind)); + allowSyscall(ctx, SCMP_SYS(bpf)); + allowSyscall(ctx, SCMP_SYS(break)); + allowSyscall(ctx, SCMP_SYS(breakpoint)); + allowSyscall(ctx, SCMP_SYS(brk)); + allowSyscall(ctx, SCMP_SYS(cachectl)); + allowSyscall(ctx, SCMP_SYS(cacheflush)); + allowSyscall(ctx, SCMP_SYS(cachestat)); + allowSyscall(ctx, SCMP_SYS(capget)); + allowSyscall(ctx, SCMP_SYS(capset)); + allowSyscall(ctx, SCMP_SYS(chdir)); + // skip chmod (dangerous) + allowSyscall(ctx, SCMP_SYS(chown)); + allowSyscall(ctx, SCMP_SYS(chown32)); + allowSyscall(ctx, SCMP_SYS(chroot)); + allowSyscall(ctx, SCMP_SYS(clock_adjtime)); + allowSyscall(ctx, SCMP_SYS(clock_adjtime64)); + allowSyscall(ctx, SCMP_SYS(clock_getres)); + allowSyscall(ctx, SCMP_SYS(clock_getres_time64)); + allowSyscall(ctx, SCMP_SYS(clock_gettime)); + allowSyscall(ctx, SCMP_SYS(clock_gettime64)); + allowSyscall(ctx, SCMP_SYS(clock_nanosleep)); + allowSyscall(ctx, SCMP_SYS(clock_nanosleep_time64)); + allowSyscall(ctx, SCMP_SYS(clock_settime)); + allowSyscall(ctx, SCMP_SYS(clock_settime64)); + allowSyscall(ctx, SCMP_SYS(clone)); + allowSyscall(ctx, SCMP_SYS(clone3)); + allowSyscall(ctx, SCMP_SYS(close)); + allowSyscall(ctx, SCMP_SYS(close_range)); + allowSyscall(ctx, SCMP_SYS(connect)); + allowSyscall(ctx, SCMP_SYS(copy_file_range)); + allowSyscall(ctx, SCMP_SYS(creat)); + allowSyscall(ctx, SCMP_SYS(create_module)); + allowSyscall(ctx, SCMP_SYS(delete_module)); + allowSyscall(ctx, SCMP_SYS(dup)); + allowSyscall(ctx, SCMP_SYS(dup2)); + allowSyscall(ctx, SCMP_SYS(dup3)); + allowSyscall(ctx, SCMP_SYS(epoll_create)); + allowSyscall(ctx, SCMP_SYS(epoll_create1)); + allowSyscall(ctx, SCMP_SYS(epoll_ctl)); + allowSyscall(ctx, SCMP_SYS(epoll_ctl_old)); + allowSyscall(ctx, SCMP_SYS(epoll_pwait)); + allowSyscall(ctx, SCMP_SYS(epoll_pwait2)); + allowSyscall(ctx, SCMP_SYS(epoll_wait)); + allowSyscall(ctx, SCMP_SYS(epoll_wait_old)); + allowSyscall(ctx, SCMP_SYS(eventfd)); + allowSyscall(ctx, SCMP_SYS(eventfd2)); + allowSyscall(ctx, SCMP_SYS(execve)); + allowSyscall(ctx, SCMP_SYS(execveat)); + allowSyscall(ctx, SCMP_SYS(exit)); + allowSyscall(ctx, SCMP_SYS(exit_group)); + allowSyscall(ctx, SCMP_SYS(faccessat)); + allowSyscall(ctx, SCMP_SYS(faccessat2)); + allowSyscall(ctx, SCMP_SYS(fadvise64)); + allowSyscall(ctx, SCMP_SYS(fadvise64_64)); + allowSyscall(ctx, SCMP_SYS(fallocate)); + allowSyscall(ctx, SCMP_SYS(fanotify_init)); + allowSyscall(ctx, SCMP_SYS(fanotify_mark)); + allowSyscall(ctx, SCMP_SYS(fchdir)); + // skip fchmod (dangerous) + // skip fchmodat (dangerous) + // skip fchmodat2 (dangerous) + allowSyscall(ctx, SCMP_SYS(fchown)); + allowSyscall(ctx, SCMP_SYS(fchown32)); + allowSyscall(ctx, SCMP_SYS(fchownat)); + allowSyscall(ctx, SCMP_SYS(fcntl)); + allowSyscall(ctx, SCMP_SYS(fcntl64)); + allowSyscall(ctx, SCMP_SYS(fdatasync)); + allowSyscall(ctx, SCMP_SYS(fgetxattr)); + allowSyscall(ctx, SCMP_SYS(finit_module)); + allowSyscall(ctx, SCMP_SYS(flistxattr)); + allowSyscall(ctx, SCMP_SYS(flock)); + allowSyscall(ctx, SCMP_SYS(fork)); + allowSyscall(ctx, SCMP_SYS(fremovexattr)); + allowSyscall(ctx, SCMP_SYS(fsconfig)); + // skip fsetxattr (dangerous) + allowSyscall(ctx, SCMP_SYS(fsmount)); + allowSyscall(ctx, SCMP_SYS(fsopen)); + allowSyscall(ctx, SCMP_SYS(fspick)); + allowSyscall(ctx, SCMP_SYS(fstat)); + allowSyscall(ctx, SCMP_SYS(fstat64)); + allowSyscall(ctx, SCMP_SYS(fstatat64)); + allowSyscall(ctx, SCMP_SYS(fstatfs)); + allowSyscall(ctx, SCMP_SYS(fstatfs64)); + allowSyscall(ctx, SCMP_SYS(fsync)); + allowSyscall(ctx, SCMP_SYS(ftime)); + allowSyscall(ctx, SCMP_SYS(ftruncate)); + allowSyscall(ctx, SCMP_SYS(ftruncate64)); + allowSyscall(ctx, SCMP_SYS(futex)); + allowSyscall(ctx, SCMP_SYS(futex_requeue)); + allowSyscall(ctx, SCMP_SYS(futex_time64)); + allowSyscall(ctx, SCMP_SYS(futex_wait)); + allowSyscall(ctx, SCMP_SYS(futex_waitv)); + allowSyscall(ctx, SCMP_SYS(futex_wake)); + allowSyscall(ctx, SCMP_SYS(futimesat)); + allowSyscall(ctx, SCMP_SYS(getcpu)); + allowSyscall(ctx, SCMP_SYS(getcwd)); + allowSyscall(ctx, SCMP_SYS(getdents)); + allowSyscall(ctx, SCMP_SYS(getdents64)); + allowSyscall(ctx, SCMP_SYS(getegid)); + allowSyscall(ctx, SCMP_SYS(getegid32)); + allowSyscall(ctx, SCMP_SYS(geteuid)); + allowSyscall(ctx, SCMP_SYS(geteuid32)); + allowSyscall(ctx, SCMP_SYS(getgid)); + allowSyscall(ctx, SCMP_SYS(getgid32)); + allowSyscall(ctx, SCMP_SYS(getgroups)); + allowSyscall(ctx, SCMP_SYS(getgroups32)); + allowSyscall(ctx, SCMP_SYS(getitimer)); + allowSyscall(ctx, SCMP_SYS(get_kernel_syms)); + allowSyscall(ctx, SCMP_SYS(get_mempolicy)); + allowSyscall(ctx, SCMP_SYS(getpeername)); + allowSyscall(ctx, SCMP_SYS(getpgid)); + allowSyscall(ctx, SCMP_SYS(getpgrp)); + allowSyscall(ctx, SCMP_SYS(getpid)); + allowSyscall(ctx, SCMP_SYS(getpmsg)); + allowSyscall(ctx, SCMP_SYS(getppid)); + allowSyscall(ctx, SCMP_SYS(getpriority)); + allowSyscall(ctx, SCMP_SYS(getrandom)); + allowSyscall(ctx, SCMP_SYS(getresgid)); + allowSyscall(ctx, SCMP_SYS(getresgid32)); + allowSyscall(ctx, SCMP_SYS(getresuid)); + allowSyscall(ctx, SCMP_SYS(getresuid32)); + allowSyscall(ctx, SCMP_SYS(getrlimit)); + allowSyscall(ctx, SCMP_SYS(get_robust_list)); + allowSyscall(ctx, SCMP_SYS(getrusage)); + allowSyscall(ctx, SCMP_SYS(getsid)); + allowSyscall(ctx, SCMP_SYS(getsockname)); + allowSyscall(ctx, SCMP_SYS(getsockopt)); + allowSyscall(ctx, SCMP_SYS(get_thread_area)); + allowSyscall(ctx, SCMP_SYS(gettid)); + allowSyscall(ctx, SCMP_SYS(gettimeofday)); + allowSyscall(ctx, SCMP_SYS(get_tls)); + allowSyscall(ctx, SCMP_SYS(getuid)); + allowSyscall(ctx, SCMP_SYS(getuid32)); + allowSyscall(ctx, SCMP_SYS(getxattr)); + allowSyscall(ctx, SCMP_SYS(gtty)); + allowSyscall(ctx, SCMP_SYS(idle)); + allowSyscall(ctx, SCMP_SYS(init_module)); + allowSyscall(ctx, SCMP_SYS(inotify_add_watch)); + allowSyscall(ctx, SCMP_SYS(inotify_init)); + allowSyscall(ctx, SCMP_SYS(inotify_init1)); + allowSyscall(ctx, SCMP_SYS(inotify_rm_watch)); + allowSyscall(ctx, SCMP_SYS(io_cancel)); + allowSyscall(ctx, SCMP_SYS(ioctl)); + allowSyscall(ctx, SCMP_SYS(io_destroy)); + allowSyscall(ctx, SCMP_SYS(io_getevents)); + allowSyscall(ctx, SCMP_SYS(ioperm)); + allowSyscall(ctx, SCMP_SYS(io_pgetevents)); + allowSyscall(ctx, SCMP_SYS(io_pgetevents_time64)); + allowSyscall(ctx, SCMP_SYS(iopl)); + allowSyscall(ctx, SCMP_SYS(ioprio_get)); + allowSyscall(ctx, SCMP_SYS(ioprio_set)); + allowSyscall(ctx, SCMP_SYS(io_setup)); + allowSyscall(ctx, SCMP_SYS(io_submit)); + // skip io_uring_enter (may become dangerous) + // skip io_uring_register (may become dangerous) + // skip io_uring_setup (may become dangerous) + allowSyscall(ctx, SCMP_SYS(ipc)); + allowSyscall(ctx, SCMP_SYS(kcmp)); + allowSyscall(ctx, SCMP_SYS(kexec_file_load)); + allowSyscall(ctx, SCMP_SYS(kexec_load)); + allowSyscall(ctx, SCMP_SYS(keyctl)); + allowSyscall(ctx, SCMP_SYS(kill)); + allowSyscall(ctx, SCMP_SYS(landlock_add_rule)); + allowSyscall(ctx, SCMP_SYS(landlock_create_ruleset)); + allowSyscall(ctx, SCMP_SYS(landlock_restrict_self)); + allowSyscall(ctx, SCMP_SYS(lchown)); + allowSyscall(ctx, SCMP_SYS(lchown32)); + allowSyscall(ctx, SCMP_SYS(lgetxattr)); + allowSyscall(ctx, SCMP_SYS(link)); + allowSyscall(ctx, SCMP_SYS(linkat)); + allowSyscall(ctx, SCMP_SYS(listen)); + allowSyscall(ctx, SCMP_SYS(listxattr)); + allowSyscall(ctx, SCMP_SYS(llistxattr)); + allowSyscall(ctx, SCMP_SYS(_llseek)); + allowSyscall(ctx, SCMP_SYS(lock)); + allowSyscall(ctx, SCMP_SYS(lookup_dcookie)); + allowSyscall(ctx, SCMP_SYS(lremovexattr)); + allowSyscall(ctx, SCMP_SYS(lseek)); + // skip lsetxattr (dangerous) + allowSyscall(ctx, SCMP_SYS(lstat)); + allowSyscall(ctx, SCMP_SYS(lstat64)); + allowSyscall(ctx, SCMP_SYS(madvise)); + allowSyscall(ctx, SCMP_SYS(map_shadow_stack)); + allowSyscall(ctx, SCMP_SYS(mbind)); + allowSyscall(ctx, SCMP_SYS(membarrier)); + allowSyscall(ctx, SCMP_SYS(memfd_create)); + allowSyscall(ctx, SCMP_SYS(memfd_secret)); + allowSyscall(ctx, SCMP_SYS(migrate_pages)); + allowSyscall(ctx, SCMP_SYS(mincore)); + allowSyscall(ctx, SCMP_SYS(mkdir)); + allowSyscall(ctx, SCMP_SYS(mkdirat)); + allowSyscall(ctx, SCMP_SYS(mknod)); + allowSyscall(ctx, SCMP_SYS(mknodat)); + allowSyscall(ctx, SCMP_SYS(mlock)); + allowSyscall(ctx, SCMP_SYS(mlock2)); + allowSyscall(ctx, SCMP_SYS(mlockall)); + allowSyscall(ctx, SCMP_SYS(mmap)); + allowSyscall(ctx, SCMP_SYS(mmap2)); + allowSyscall(ctx, SCMP_SYS(modify_ldt)); + allowSyscall(ctx, SCMP_SYS(mount)); + allowSyscall(ctx, SCMP_SYS(mount_setattr)); + allowSyscall(ctx, SCMP_SYS(move_mount)); + allowSyscall(ctx, SCMP_SYS(move_pages)); + allowSyscall(ctx, SCMP_SYS(mprotect)); + allowSyscall(ctx, SCMP_SYS(mpx)); + allowSyscall(ctx, SCMP_SYS(mq_getsetattr)); + allowSyscall(ctx, SCMP_SYS(mq_notify)); + allowSyscall(ctx, SCMP_SYS(mq_open)); + allowSyscall(ctx, SCMP_SYS(mq_timedreceive)); + allowSyscall(ctx, SCMP_SYS(mq_timedreceive_time64)); + allowSyscall(ctx, SCMP_SYS(mq_timedsend)); + allowSyscall(ctx, SCMP_SYS(mq_timedsend_time64)); + allowSyscall(ctx, SCMP_SYS(mq_unlink)); + allowSyscall(ctx, SCMP_SYS(mremap)); + allowSyscall(ctx, SCMP_SYS(msgctl)); + allowSyscall(ctx, SCMP_SYS(msgget)); + allowSyscall(ctx, SCMP_SYS(msgrcv)); + allowSyscall(ctx, SCMP_SYS(msgsnd)); + allowSyscall(ctx, SCMP_SYS(msync)); + allowSyscall(ctx, SCMP_SYS(multiplexer)); + allowSyscall(ctx, SCMP_SYS(munlock)); + allowSyscall(ctx, SCMP_SYS(munlockall)); + allowSyscall(ctx, SCMP_SYS(munmap)); + allowSyscall(ctx, SCMP_SYS(name_to_handle_at)); + allowSyscall(ctx, SCMP_SYS(nanosleep)); + allowSyscall(ctx, SCMP_SYS(newfstatat)); + allowSyscall(ctx, SCMP_SYS(_newselect)); + allowSyscall(ctx, SCMP_SYS(nfsservctl)); + allowSyscall(ctx, SCMP_SYS(nice)); + allowSyscall(ctx, SCMP_SYS(oldfstat)); + allowSyscall(ctx, SCMP_SYS(oldlstat)); + allowSyscall(ctx, SCMP_SYS(oldolduname)); + allowSyscall(ctx, SCMP_SYS(oldstat)); + allowSyscall(ctx, SCMP_SYS(olduname)); + allowSyscall(ctx, SCMP_SYS(open)); + allowSyscall(ctx, SCMP_SYS(openat)); + allowSyscall(ctx, SCMP_SYS(openat2)); + allowSyscall(ctx, SCMP_SYS(open_by_handle_at)); + allowSyscall(ctx, SCMP_SYS(open_tree)); + allowSyscall(ctx, SCMP_SYS(pause)); + allowSyscall(ctx, SCMP_SYS(pciconfig_iobase)); + allowSyscall(ctx, SCMP_SYS(pciconfig_read)); + allowSyscall(ctx, SCMP_SYS(pciconfig_write)); + allowSyscall(ctx, SCMP_SYS(perf_event_open)); + allowSyscall(ctx, SCMP_SYS(personality)); + allowSyscall(ctx, SCMP_SYS(pidfd_getfd)); + allowSyscall(ctx, SCMP_SYS(pidfd_open)); + allowSyscall(ctx, SCMP_SYS(pidfd_send_signal)); + allowSyscall(ctx, SCMP_SYS(pipe)); + allowSyscall(ctx, SCMP_SYS(pipe2)); + allowSyscall(ctx, SCMP_SYS(pivot_root)); + allowSyscall(ctx, SCMP_SYS(pkey_alloc)); + allowSyscall(ctx, SCMP_SYS(pkey_free)); + allowSyscall(ctx, SCMP_SYS(pkey_mprotect)); + allowSyscall(ctx, SCMP_SYS(poll)); + allowSyscall(ctx, SCMP_SYS(ppoll)); + allowSyscall(ctx, SCMP_SYS(ppoll_time64)); + allowSyscall(ctx, SCMP_SYS(prctl)); + allowSyscall(ctx, SCMP_SYS(pread64)); + allowSyscall(ctx, SCMP_SYS(preadv)); + allowSyscall(ctx, SCMP_SYS(preadv2)); + allowSyscall(ctx, SCMP_SYS(prlimit64)); + allowSyscall(ctx, SCMP_SYS(process_madvise)); + allowSyscall(ctx, SCMP_SYS(process_mrelease)); + allowSyscall(ctx, SCMP_SYS(process_vm_readv)); + allowSyscall(ctx, SCMP_SYS(process_vm_writev)); + allowSyscall(ctx, SCMP_SYS(prof)); + allowSyscall(ctx, SCMP_SYS(profil)); + allowSyscall(ctx, SCMP_SYS(pselect6)); + allowSyscall(ctx, SCMP_SYS(pselect6_time64)); + allowSyscall(ctx, SCMP_SYS(ptrace)); + allowSyscall(ctx, SCMP_SYS(putpmsg)); + allowSyscall(ctx, SCMP_SYS(pwrite64)); + allowSyscall(ctx, SCMP_SYS(pwritev)); + allowSyscall(ctx, SCMP_SYS(pwritev2)); + allowSyscall(ctx, SCMP_SYS(query_module)); + allowSyscall(ctx, SCMP_SYS(quotactl)); + allowSyscall(ctx, SCMP_SYS(quotactl_fd)); + allowSyscall(ctx, SCMP_SYS(read)); + allowSyscall(ctx, SCMP_SYS(readahead)); + allowSyscall(ctx, SCMP_SYS(readdir)); + allowSyscall(ctx, SCMP_SYS(readlink)); + allowSyscall(ctx, SCMP_SYS(readlinkat)); + allowSyscall(ctx, SCMP_SYS(readv)); + allowSyscall(ctx, SCMP_SYS(reboot)); + allowSyscall(ctx, SCMP_SYS(recv)); + allowSyscall(ctx, SCMP_SYS(recvfrom)); + allowSyscall(ctx, SCMP_SYS(recvmmsg)); + allowSyscall(ctx, SCMP_SYS(recvmmsg_time64)); + allowSyscall(ctx, SCMP_SYS(recvmsg)); + allowSyscall(ctx, SCMP_SYS(remap_file_pages)); + allowSyscall(ctx, SCMP_SYS(removexattr)); + allowSyscall(ctx, SCMP_SYS(rename)); + allowSyscall(ctx, SCMP_SYS(renameat)); + allowSyscall(ctx, SCMP_SYS(renameat2)); + allowSyscall(ctx, SCMP_SYS(request_key)); + allowSyscall(ctx, SCMP_SYS(restart_syscall)); + allowSyscall(ctx, SCMP_SYS(riscv_flush_icache)); + allowSyscall(ctx, SCMP_SYS(rmdir)); + allowSyscall(ctx, SCMP_SYS(rseq)); + allowSyscall(ctx, SCMP_SYS(rtas)); + allowSyscall(ctx, SCMP_SYS(rt_sigaction)); + allowSyscall(ctx, SCMP_SYS(rt_sigpending)); + allowSyscall(ctx, SCMP_SYS(rt_sigprocmask)); + allowSyscall(ctx, SCMP_SYS(rt_sigqueueinfo)); + allowSyscall(ctx, SCMP_SYS(rt_sigreturn)); + allowSyscall(ctx, SCMP_SYS(rt_sigsuspend)); + allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait)); + allowSyscall(ctx, SCMP_SYS(rt_sigtimedwait_time64)); + allowSyscall(ctx, SCMP_SYS(rt_tgsigqueueinfo)); + allowSyscall(ctx, SCMP_SYS(s390_guarded_storage)); + allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_read)); + allowSyscall(ctx, SCMP_SYS(s390_pci_mmio_write)); + allowSyscall(ctx, SCMP_SYS(s390_runtime_instr)); + allowSyscall(ctx, SCMP_SYS(s390_sthyi)); + allowSyscall(ctx, SCMP_SYS(sched_getaffinity)); + allowSyscall(ctx, SCMP_SYS(sched_getattr)); + allowSyscall(ctx, SCMP_SYS(sched_getparam)); + allowSyscall(ctx, SCMP_SYS(sched_get_priority_max)); + allowSyscall(ctx, SCMP_SYS(sched_get_priority_min)); + allowSyscall(ctx, SCMP_SYS(sched_getscheduler)); + allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval)); + allowSyscall(ctx, SCMP_SYS(sched_rr_get_interval_time64)); + allowSyscall(ctx, SCMP_SYS(sched_setaffinity)); + allowSyscall(ctx, SCMP_SYS(sched_setattr)); + allowSyscall(ctx, SCMP_SYS(sched_setparam)); + allowSyscall(ctx, SCMP_SYS(sched_setscheduler)); + allowSyscall(ctx, SCMP_SYS(sched_yield)); + allowSyscall(ctx, SCMP_SYS(seccomp)); + allowSyscall(ctx, SCMP_SYS(security)); + allowSyscall(ctx, SCMP_SYS(select)); + allowSyscall(ctx, SCMP_SYS(semctl)); + allowSyscall(ctx, SCMP_SYS(semget)); + allowSyscall(ctx, SCMP_SYS(semop)); + allowSyscall(ctx, SCMP_SYS(semtimedop)); + allowSyscall(ctx, SCMP_SYS(semtimedop_time64)); + allowSyscall(ctx, SCMP_SYS(send)); + allowSyscall(ctx, SCMP_SYS(sendfile)); + allowSyscall(ctx, SCMP_SYS(sendfile64)); + allowSyscall(ctx, SCMP_SYS(sendmmsg)); + allowSyscall(ctx, SCMP_SYS(sendmsg)); + allowSyscall(ctx, SCMP_SYS(sendto)); + allowSyscall(ctx, SCMP_SYS(setdomainname)); + allowSyscall(ctx, SCMP_SYS(setfsgid)); + allowSyscall(ctx, SCMP_SYS(setfsgid32)); + allowSyscall(ctx, SCMP_SYS(setfsuid)); + allowSyscall(ctx, SCMP_SYS(setfsuid32)); + allowSyscall(ctx, SCMP_SYS(setgid)); + allowSyscall(ctx, SCMP_SYS(setgid32)); + allowSyscall(ctx, SCMP_SYS(setgroups)); + allowSyscall(ctx, SCMP_SYS(setgroups32)); + allowSyscall(ctx, SCMP_SYS(sethostname)); + allowSyscall(ctx, SCMP_SYS(setitimer)); + allowSyscall(ctx, SCMP_SYS(set_mempolicy)); + allowSyscall(ctx, SCMP_SYS(set_mempolicy_home_node)); + allowSyscall(ctx, SCMP_SYS(setns)); + allowSyscall(ctx, SCMP_SYS(setpgid)); + allowSyscall(ctx, SCMP_SYS(setpriority)); + allowSyscall(ctx, SCMP_SYS(setregid)); + allowSyscall(ctx, SCMP_SYS(setregid32)); + allowSyscall(ctx, SCMP_SYS(setresgid)); + allowSyscall(ctx, SCMP_SYS(setresgid32)); + allowSyscall(ctx, SCMP_SYS(setresuid)); + allowSyscall(ctx, SCMP_SYS(setresuid32)); + allowSyscall(ctx, SCMP_SYS(setreuid)); + allowSyscall(ctx, SCMP_SYS(setreuid32)); + allowSyscall(ctx, SCMP_SYS(setrlimit)); + allowSyscall(ctx, SCMP_SYS(set_robust_list)); + allowSyscall(ctx, SCMP_SYS(setsid)); + allowSyscall(ctx, SCMP_SYS(setsockopt)); + allowSyscall(ctx, SCMP_SYS(set_thread_area)); + allowSyscall(ctx, SCMP_SYS(set_tid_address)); + allowSyscall(ctx, SCMP_SYS(settimeofday)); + allowSyscall(ctx, SCMP_SYS(set_tls)); + allowSyscall(ctx, SCMP_SYS(setuid)); + allowSyscall(ctx, SCMP_SYS(setuid32)); + // skip setxattr (dangerous) + allowSyscall(ctx, SCMP_SYS(sgetmask)); + allowSyscall(ctx, SCMP_SYS(shmat)); + allowSyscall(ctx, SCMP_SYS(shmctl)); + allowSyscall(ctx, SCMP_SYS(shmdt)); + allowSyscall(ctx, SCMP_SYS(shmget)); + allowSyscall(ctx, SCMP_SYS(shutdown)); + allowSyscall(ctx, SCMP_SYS(sigaction)); + allowSyscall(ctx, SCMP_SYS(sigaltstack)); + allowSyscall(ctx, SCMP_SYS(signal)); + allowSyscall(ctx, SCMP_SYS(signalfd)); + allowSyscall(ctx, SCMP_SYS(signalfd4)); + allowSyscall(ctx, SCMP_SYS(sigpending)); + allowSyscall(ctx, SCMP_SYS(sigprocmask)); + allowSyscall(ctx, SCMP_SYS(sigreturn)); + allowSyscall(ctx, SCMP_SYS(sigsuspend)); + allowSyscall(ctx, SCMP_SYS(socket)); + allowSyscall(ctx, SCMP_SYS(socketcall)); + allowSyscall(ctx, SCMP_SYS(socketpair)); + allowSyscall(ctx, SCMP_SYS(splice)); + allowSyscall(ctx, SCMP_SYS(spu_create)); + allowSyscall(ctx, SCMP_SYS(spu_run)); + allowSyscall(ctx, SCMP_SYS(ssetmask)); + allowSyscall(ctx, SCMP_SYS(stat)); + allowSyscall(ctx, SCMP_SYS(stat64)); + allowSyscall(ctx, SCMP_SYS(statfs)); + allowSyscall(ctx, SCMP_SYS(statfs64)); + allowSyscall(ctx, SCMP_SYS(statx)); + allowSyscall(ctx, SCMP_SYS(stime)); + allowSyscall(ctx, SCMP_SYS(stty)); + allowSyscall(ctx, SCMP_SYS(subpage_prot)); + allowSyscall(ctx, SCMP_SYS(swapcontext)); + allowSyscall(ctx, SCMP_SYS(swapoff)); + allowSyscall(ctx, SCMP_SYS(swapon)); + allowSyscall(ctx, SCMP_SYS(switch_endian)); + allowSyscall(ctx, SCMP_SYS(symlink)); + allowSyscall(ctx, SCMP_SYS(symlinkat)); + allowSyscall(ctx, SCMP_SYS(sync)); + allowSyscall(ctx, SCMP_SYS(sync_file_range)); + allowSyscall(ctx, SCMP_SYS(sync_file_range2)); + allowSyscall(ctx, SCMP_SYS(syncfs)); + allowSyscall(ctx, SCMP_SYS(syscall)); + allowSyscall(ctx, SCMP_SYS(_sysctl)); + allowSyscall(ctx, SCMP_SYS(sys_debug_setcontext)); + allowSyscall(ctx, SCMP_SYS(sysfs)); + allowSyscall(ctx, SCMP_SYS(sysinfo)); + allowSyscall(ctx, SCMP_SYS(syslog)); + allowSyscall(ctx, SCMP_SYS(sysmips)); + allowSyscall(ctx, SCMP_SYS(tee)); + allowSyscall(ctx, SCMP_SYS(tgkill)); + allowSyscall(ctx, SCMP_SYS(time)); + allowSyscall(ctx, SCMP_SYS(timer_create)); + allowSyscall(ctx, SCMP_SYS(timer_delete)); + allowSyscall(ctx, SCMP_SYS(timerfd)); + allowSyscall(ctx, SCMP_SYS(timerfd_create)); + allowSyscall(ctx, SCMP_SYS(timerfd_gettime)); + allowSyscall(ctx, SCMP_SYS(timerfd_gettime64)); + allowSyscall(ctx, SCMP_SYS(timerfd_settime)); + allowSyscall(ctx, SCMP_SYS(timerfd_settime64)); + allowSyscall(ctx, SCMP_SYS(timer_getoverrun)); + allowSyscall(ctx, SCMP_SYS(timer_gettime)); + allowSyscall(ctx, SCMP_SYS(timer_gettime64)); + allowSyscall(ctx, SCMP_SYS(timer_settime)); + allowSyscall(ctx, SCMP_SYS(timer_settime64)); + allowSyscall(ctx, SCMP_SYS(times)); + allowSyscall(ctx, SCMP_SYS(tkill)); + allowSyscall(ctx, SCMP_SYS(truncate)); + allowSyscall(ctx, SCMP_SYS(truncate64)); + allowSyscall(ctx, SCMP_SYS(tuxcall)); + allowSyscall(ctx, SCMP_SYS(ugetrlimit)); + allowSyscall(ctx, SCMP_SYS(ulimit)); + allowSyscall(ctx, SCMP_SYS(umask)); + allowSyscall(ctx, SCMP_SYS(umount)); + allowSyscall(ctx, SCMP_SYS(umount2)); + allowSyscall(ctx, SCMP_SYS(uname)); + allowSyscall(ctx, SCMP_SYS(unlink)); + allowSyscall(ctx, SCMP_SYS(unlinkat)); + allowSyscall(ctx, SCMP_SYS(unshare)); + allowSyscall(ctx, SCMP_SYS(uselib)); + allowSyscall(ctx, SCMP_SYS(userfaultfd)); + allowSyscall(ctx, SCMP_SYS(usr26)); + allowSyscall(ctx, SCMP_SYS(usr32)); + allowSyscall(ctx, SCMP_SYS(ustat)); + allowSyscall(ctx, SCMP_SYS(utime)); + allowSyscall(ctx, SCMP_SYS(utimensat)); + allowSyscall(ctx, SCMP_SYS(utimensat_time64)); + allowSyscall(ctx, SCMP_SYS(utimes)); + allowSyscall(ctx, SCMP_SYS(vfork)); + allowSyscall(ctx, SCMP_SYS(vhangup)); + allowSyscall(ctx, SCMP_SYS(vm86)); + allowSyscall(ctx, SCMP_SYS(vm86old)); + allowSyscall(ctx, SCMP_SYS(vmsplice)); + allowSyscall(ctx, SCMP_SYS(vserver)); + allowSyscall(ctx, SCMP_SYS(wait4)); + allowSyscall(ctx, SCMP_SYS(waitid)); + allowSyscall(ctx, SCMP_SYS(waitpid)); + allowSyscall(ctx, SCMP_SYS(write)); + allowSyscall(ctx, SCMP_SYS(writev)); + // END extract-syscalls + + // chmod family: prevent adding setuid/setgid bits to existing files. + // The Nix store does not support setuid/setgid, and even their temporary creation can weaken the security of the sandbox. + ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(chmod), 1); + ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmod), 1); + ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat), 2); + ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat2), 2); + + // setxattr family: prevent creation of extended attributes or ACLs. + // Not all filesystems support them, and they're incompatible with the NAR format. + if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 || + seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 || + seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0) + throw SysError("unable to add seccomp rule"); + + Pipe filterPipe; + filterPipe.create(); + auto filterBytes_ = std::async([&]() { + return drainFD(filterPipe.readSide.get()); + }); + if (seccomp_export_bpf(ctx, filterPipe.writeSide.get()) != 0) + throw SysError("unable to compile seccomp BPF program"); + filterPipe.writeSide.close(); + auto filterBytes = filterBytes_.get(); + + assert(filterBytes.size() % sizeof(struct sock_filter) == 0); + std::vector<struct sock_filter> filter(filterBytes.size() / sizeof(struct sock_filter)); + std::memcpy(filter.data(), filterBytes.data(), filterBytes.size()); + return filter; +} + +static const std::vector<struct sock_filter> &getSyscallFilter() +{ + static auto filter = compileSyscallFilter(); + return filter; +} + +#endif + +void LinuxLocalDerivationGoal::setupSyscallFilter() +{ + // Set the NO_NEW_PRIVS prctl flag. + // This both makes loading seccomp filters work for unprivileged users, + // and is an additional security measure in its own right. + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) + throw SysError("PR_SET_NO_NEW_PRIVS failed"); +#if HAVE_SECCOMP + const auto &seccompBPF = getSyscallFilter(); + assert(seccompBPF.size() <= std::numeric_limits<unsigned short>::max()); + struct sock_fprog fprog = { + .len = static_cast<unsigned short>(seccompBPF.size()), + // the kernel does not actually write to the filter + .filter = const_cast<struct sock_filter *>(seccompBPF.data()), + }; + if (syscall(SYS_seccomp, SECCOMP_SET_MODE_FILTER, 0, &fprog) != 0) + throw SysError("unable to load seccomp BPF program"); +#endif +} + void LinuxLocalDerivationGoal::prepareSandbox() { /* Create a temporary directory in which we set up the chroot @@ -208,6 +834,13 @@ void LinuxLocalDerivationGoal::prepareSandbox() Pid LinuxLocalDerivationGoal::startChild(std::function<void()> openSlave) { +#if HAVE_SECCOMP + // Our seccomp filter program is surprisingly expensive to compile (~10ms). + // For this reason, we precompile it once and then cache it. + // This has to be done in the parent so that all builds get to use the same cache. + getSyscallFilter(); +#endif + // If we're not sandboxing no need to faff about, use the fallback if (!useChroot) { return LocalDerivationGoal::startChild(openSlave); diff --git a/src/libstore/platform/linux.hh b/src/libstore/platform/linux.hh index 2173205bc..c8842e09c 100644 --- a/src/libstore/platform/linux.hh +++ b/src/libstore/platform/linux.hh @@ -59,6 +59,11 @@ private: */ void killSandbox(bool getStatus) override; + /** + * Set up system call filtering using seccomp, unless disabled at build time. + * This also sets the NO_NEW_PRIVS flag. + */ + void setupSyscallFilter() override; bool supportsUidRange() override { |