Skip to content

Seccomp Profile ​

On Linux, go-judge applies an embedded, architecture-aware seccomp filter to sandbox workloads by default. The filter is based on a vendored snapshot of Moby's default profile, then converted and tightened for go-judge. It has a default action of errno: syscalls outside the allowlist fail with an error. A denied syscall normally causes the command to finish with status Dangerous Syscall.

When the filter is applied ​

The container init process completes namespace, filesystem, and cgroup setup before installing the filter. Workload processes inherit it when they start; go-judge does not install a separate filter for every command. The init setup can use operations such as clone, clone3, unshare, and kill before the workload filter is installed.

The generated profile has shared rules plus architecture-specific syscall rules for x86-64, i386, AArch64, and ARM. Syscall names are resolved for each architecture when the profile is generated and loaded.

Why the profile differs from Moby's baseline ​

The converter removes Moby rules that depend on container capabilities. go-judge drops capabilities before executing submitted programs, so those conditional rules do not describe the workload's effective permissions. Architecture selectors are resolved into explicit per-architecture rules.

The policy also removes syscall groups that were absent from the compiler and runtime workloads used to build the profile and that add authority or kernel attack surface:

  • Cross-process inspection and control: ptrace, process_vm_readv, process_vm_writev, process_mrelease, and get_robust_list can expose or affect other processes.
  • Alternate executable loading: execveat, memfd_create, and memfd_secret add fileless executable loading or staging paths.
  • Legacy x86 execution state: modify_ldt, get_thread_area, and set_thread_area expose legacy compatibility interfaces.
  • Device nodes and filesystem event attachment: mknod, mknodat, and fanotify_mark can expose devices or monitor filesystem activity beyond ordinary file access.
  • Cross-process signaling and scheduling: getsid, rt_sigqueueinfo, rt_tgsigqueueinfo, sched_setattr, sched_setparam, and tkill can identify or affect other processes. getpgid is restricted to querying the calling process because shells use that form for job control.
  • Legacy asynchronous I/O: io_setup, io_submit, io_getevents, io_pgetevents, io_destroy, and io_cancel add an unused I/O interface.
  • Alternate filesystem and mount interfaces: openat2, name_to_handle_at, listmount, and statmount add interfaces beyond the file operations observed in workloads.
  • Kernel-mediated data transfer: copy_file_range, sendfile, splice, tee, and vmsplice provide descriptor-to-descriptor transfer paths that workloads do not need.

The profile also denies personality and restricts ioctl by blocking terminal input injection and Linux virtual-console requests. Socket creation is limited to AF_UNIX, AF_INET, and AF_INET6; socketpair is limited to AF_UNIX. On i386, seccomp cannot inspect the pointed-to arguments used by the legacy socketcall interface, so its socket and socketpair operations are denied. These rules reduce available kernel interfaces; they do not by themselves provide network namespace isolation.

Allowed syscall list and compiler observations ​

The lists below are the syscall names present in the current generated profile across its shared and architecture-specific sections. Architecture sections include ABI aliases; a syscall can be unavailable on a different architecture. Several calls have argument filters rather than unrestricted access: socket is limited to AF_UNIX, AF_INET, and AF_INET6; socketpair to AF_UNIX; ioctl excludes TIOCSTI and TIOCLINUX; and getpgid is limited to querying the current process. The i386 socketcall path denies socket creation.

Compiler associations below report observed use in a sample corpus of 16 language configurations, not a guarantee that every feature of each compiler requires only these calls. Most ordinary file, memory, process, identity, and resource calls were seen across the corpus. The upstream observation records calls by language and compile/run phase.

Compiler observations ​

Observed workloadCalls that stood out in the trace
Go compilerclone, pidfd_open, pidfd_send_signal, and fallocate appeared during compilation.
Java compiler/runtimesocket was used during compile and run. The profile permits only AF_UNIX, AF_INET, and AF_INET6; AF_UNIX and internet-family sockets were observed in Java compilation, and AF_UNIX in runtime.
Rust compilersocketpair(AF_UNIX) appeared during compilation.
Other sampled workloadsThe common file, memory, process, identity, and resource calls appear across the 16 sampled language configurations. The source observation lists each language and phase separately.

File and directory operations ​

_llseek, access, chdir, chmod, chown, chown32, close, close_range, creat, faccessat, faccessat2, fadvise64, fadvise64_64, fallocate, fchdir, fchmod, fchmodat, fchmodat2, fchown, fchown32, fchownat, fcntl, fcntl64, fdatasync, fgetxattr, flistxattr, flock, fremovexattr, fsetxattr, fstat, fstat64, fstatat, fstatat64, fstatfs, fstatfs64, fsync, ftruncate, ftruncate64, getcwd, getdents, getdents64, getxattr, getxattrat, lgetxattr, link, linkat, listxattr, listxattrat, llistxattr, lremovexattr, lseek, lsetxattr, lstat, lstat64, mkdir, mkdirat, newfstatat, open, openat, read, readahead, readlink, readlinkat, readv, removexattr, removexattrat, rename, renameat, renameat2, rmdir, setxattr, setxattrat, stat, stat64, statfs, statfs64, statx, sync, sync_file_range, syncfs, truncate, truncate64, umask, unlink, unlinkat, utime, utimensat, utimensat_time64, utimes, write, writev

Memory management ​

brk, madvise, mincore, mlock, mlock2, mlockall, mmap, mmap2, mprotect, mremap, mseal, munlock, munlockall, munmap, pkey_alloc, pkey_free, pkey_mprotect, remap_file_pages

Process, thread, and signal control ​

clone, clone3, execve, exit, exit_group, fork, getpgid, getpgrp, getpid, getppid, gettid, kill, pidfd_open, pidfd_send_signal, prctl, rt_sigaction, rt_sigpending, rt_sigprocmask, rt_sigreturn, rt_sigsuspend, rt_sigtimedwait, rt_sigtimedwait_time64, set_robust_list, set_tid_address, setpgid, setsid, sigaltstack, tgkill, vfork, wait4, waitid, waitpid

Time and timers ​

alarm, clock_adjtime, clock_adjtime64, clock_getres, clock_getres_time64, clock_gettime, clock_gettime64, clock_nanosleep, clock_nanosleep_time64, getcpu, getrusage, gettimeofday, nanosleep, setitimer, sysinfo, timer_create, timer_delete, timer_getoverrun, timer_gettime, timer_gettime64, timer_settime, timer_settime64, timerfd_create, timerfd_gettime, timerfd_gettime64, timerfd_settime, timerfd_settime64, times

Scheduling and resource limits ​

getpriority, getrlimit, ioprio_get, ioprio_set, prlimit64, sched_get_priority_max, sched_get_priority_min, sched_getaffinity, sched_getattr, sched_getparam, sched_getscheduler, sched_rr_get_interval, sched_rr_get_interval_time64, sched_setaffinity, sched_setscheduler, sched_yield, setpriority, setrlimit, ugetrlimit

Synchronization, IPC, and polling ​

epoll_create, epoll_create1, epoll_ctl, epoll_ctl_old, epoll_pwait, epoll_pwait2, epoll_wait, epoll_wait_old, eventfd, eventfd2, futex, futex_requeue, futex_time64, futex_wait, futex_waitv, futex_wake, inotify_add_watch, inotify_init, inotify_init1, inotify_rm_watch, ipc, mq_getsetattr, mq_notify, mq_open, mq_timedreceive, mq_timedreceive_time64, mq_timedsend, mq_timedsend_time64, mq_unlink, msgctl, msgget, msgrcv, msgsnd, pipe, pipe2, poll, pselect6, pselect6_time64, select, semctl, semget, semop, semtimedop, semtimedop_time64, shmat, shmctl, shmdt, shmget, signalfd, signalfd4

Sockets and networking ​

accept, accept4, bind, connect, getpeername, getsockname, getsockopt, listen, recv, recvfrom, recvmmsg, recvmmsg_time64, recvmsg, send, sendfile64, sendmmsg, sendmsg, sendto, setsockopt, shutdown, socket, socketcall, socketpair

Credentials and system information ​

capget, capset, getegid, getegid32, geteuid, geteuid32, getgid, getgid32, getgroups, getgroups32, getrandom, getresgid, getresgid32, getresuid, getresuid32, getuid, getuid32, setfsgid, setfsgid32, setfsuid, setfsuid32, setgid, setgid32, setgroups, setgroups32, setregid, setregid32, setresgid, setresgid32, setresuid, setresuid32, setreuid, setreuid32, setuid, setuid32, uname

Architecture-specific and other operations ​

_newselect, adjtimex, arch_prctl, arm_fadvise64_64, arm_sync_file_range, breakpoint, cacheflush, cachestat, dup, dup2, dup3, futimesat, getitimer, io_pgetevents_time64, ioctl, landlock_add_rule, landlock_create_ruleset, landlock_restrict_self, lchown, lchown32, map_shadow_stack, membarrier, msync, pause, ppoll, ppoll_time64, pread64, preadv, preadv2, pwrite64, pwritev, pwritev2, restart_syscall, rseq, seccomp, set_tls, sigprocmask, sigreturn, symlink, symlinkat, time, unshare, uretprobe

Configuration ​

Use -seccomp-conf <path> to replace the embedded profile with a custom profile in go-judge's architecture-aware YAML format. Use -no-seccomp to disable the filter for troubleshooting or benchmarking; this removes an isolation layer and should not be used for normal service.

The profile source, generation notes, and implementation rationale are maintained in the go-judge seccomp directory.