Skip to content

Linux Sandbox (Landlock + seccomp)

On Linux, runok uses a combination of three kernel mechanisms to enforce sandbox policies:

MechanismControls
bubblewrapMount namespace isolation (file system layout)
Landlock LSMFile system access permissions
seccomp-bpfNetwork system call filtering

Linux sandboxing requires a two-stage execution model because the different mechanisms must be applied at different points in the process lifecycle.

runok launches itself inside bubblewrap (bwrap) using a hidden __sandbox-exec subcommand, which creates an isolated mount namespace:

  • / is mounted read-only (the entire root file system)
  • Writable directories are re-mounted with write access
  • Protected subpaths are mounted read-only on top (mount ordering ensures deny takes priority)
  • /proc and /dev are set up for the sandboxed process
  • /tmp gets a private tmpfs (unless it overlaps with a writable root)
  • All namespaces are unshared (--unshare-all), with network selectively shared back if allowed

Stage 2: Process-level restrictions (Landlock + seccomp)

Section titled “Stage 2: Process-level restrictions (Landlock + seccomp)”

Inside the bubblewrap namespace, the re-invoked runok process applies:

  1. Landlock rules for file system access control
  2. seccomp-bpf filters for network system call blocking
  3. Then replaces itself with the target command via execvp

This two-stage model is necessary because bubblewrap sets up the namespace before exec, while Landlock and seccomp must be applied within the namespace. By re-invoking itself via runok __sandbox-exec, runok achieves this without requiring a separate helper binary.

Landlock is a Linux Security Module (available since Linux 5.13) that provides unprivileged file system access control.

runok uses Landlock to define which paths are readable and writable:

  • / is granted read-only access
  • /dev/null is granted read-write access (required by many tools)
  • /dev/zero, /dev/urandom, /dev/random are granted read-only access
  • /tmp is granted read-write access (unless overlapping with a writable root)
  • Each configured writable directory is granted read-write access

runok uses Landlock ABI V5 with best-effort compatibility. On older kernels with limited Landlock support, unsupported permissions are automatically dropped. The sandbox still provides as much protection as the kernel supports.

When network.allow is false, runok installs a seccomp-bpf filter that blocks network socket creation:

  • The socket(2) system call is intercepted
  • If the socket domain is not AF_UNIX, the call returns EPERM
  • AF_UNIX (Unix domain sockets) is always allowed for local IPC

This effectively blocks TCP (AF_INET) and IPv6 (AF_INET6) connections while keeping local inter-process communication working.

All other system calls are unaffected — seccomp is only used for network control, not for general system call filtering.

The deny list in the sandbox configuration is enforced through bubblewrap’s mount ordering:

  • Literal paths (e.g., .git, /etc/shadow) are mounted read-only via --ro-bind
  • Glob patterns (e.g., .env*, ~/.ssh/**) are expanded against the filesystem at startup, and each matched real path is mounted read-only