MINIJAIL0(1)

πŸ“¦ version 2026.05.18, in nixos 26.05, nixpkgs unstable

okay so bestie, we're in minijail0(1) from the User Commands corner of the manual, and the whole vibe is: sandbox a process. No cap, that's the mission. πŸ’…

🌸 NAME 🌸

minijail0 β€” sandbox a process

✨ SYNOPSIS ✨

minijail0 [OPTION]... <PROGRAM> [args]...

πŸ’– DESCRIPTION πŸ’–

Runs PROGRAM inside a sandbox. That's the main-character energy right there. 🫢

  • -a <table> β€” Run using the alternate syscall table named table. Only available on kernels and architectures that support the PR_ALT_SYSCALL option of prctl(2).
  • -b <src>[,[dest][,<writeable>]], --bind-mount=<src>[,[dest][,<writeable>]] β€” Bind-mount src into the chroot directory at dest, optionally writeable. The src path must be an absolute path. If dest is not specified, it will default to src. If the destination does not exist, it will be created as a file or directory based on the src type, including missing parent directories. To create a writable bind-mount set writeable to 1. If not specified it will default to 0 (read-only).
  • -B <mask> β€” Skip setting securebits in mask when restricting capabilities (-c). mask is a hex constant that represents the mask of securebits that will be preserved. See capabilities(7) for the complete list. By default, SECURE_NOROOT, SECURE_NO_SETUID_FIXUP, and SECURE_KEEP_CAPS (together with their respective locks) are set. SECBIT_NO_CAP_AMBIENT_RAISE (and its respective lock) is never set because the permitted and inheritable capability sets have already been set through -c.
  • -c <caps> β€” Restrict capabilities to caps, which is either a hex constant or a string that will be passed to cap_from_text(3) (only the effective capability mask will be considered). The value will be used as the permitted, effective, and inheritable sets. When used in conjunction with -u and -g, this allows a program to have access to only certain parts of root's default privileges while running as another user and group ID altogether. Note that these capabilities are not inherited by subprocesses of the process given capabilities unless those subprocesses have POSIX file capabilities or the --ambient flag is also passed. See capabilities(7).
  • -C <dir> β€” Change root (using chroot(2)) to dir.
  • -d, --mount-dev β€” Create a new /dev mount with a minimal set of nodes. Implies -v. Additional nodes can be bound with the -b or -k options.
    • The initial set of nodes are: full null tty urandom zero.
    • Symlinks are also created for: fd ptmx stderr stdin stdout.
    • Directories are also created for: shm.
  • -e[file] β€” Enter a new network namespace, or if file is specified, enter an existing network namespace specified by file, which is typically of the form /proc/<pid>/ns/net.
  • -f <file> β€” Write the pid of the jailed process to file.
  • -g <group|gid> β€” Change groups to the specified group name, or numeric group ID gid.
  • -G β€” Inherit all the supplementary groups of the user specified with -u. It is an error to use this option without having specified a user name to -u.
  • --add-suppl-group <group|gid> β€” Add the specified group name, or numeric group ID gid, to the process' supplementary groups list. Can be specified multiple times to add several groups. Incompatible with -y and -G.
  • -h β€” Print a help message.
  • -H β€” Print a help message detailing supported system call names for seccomp_filter. (Other direct numbers may be specified if minijail0 is not in sync with the host kernel or something like 32/64-bit compatibility issues exist.)
  • -i β€” Exit immediately after fork(2). The jailed process will keep running in the background. Normally minijail will fork+exec the specified program so that it can set up the right security settings in the new child process. The initial minijail process will stay resident and wait for the program to exit so the script that ran minijail will correctly block (e.g. standalone scripts). Specifying -i makes that initial process exit immediately and free up the resources. This option is recommended for daemons and init services when you want to background the long running program.
  • -I β€” Run program as init (pid 1) inside a new pid namespace (implies -p). Most programs don't expect to run as an init which is why minijail will do it for you by default. Basically, the program needs to reap any processes it forks to avoid leaving zombies behind. Signal handling needs care since the kernel will mask all signals that don't have handlers registered (all default handlers are ignored and cannot be changed). This means a minijail process (acting as init) will remain resident by default. While using -I is recommended when possible, strict review is required to make sure the program continues to work as expected. -i and -I may be safely used together. The -i option controls the first minijail process outside of the pid namespace while the -I option controls the minijail process inside of the pid namespace.
  • -k <src>,<dest>,<type>[,<flags>[,<data>]], --mount=<src>,<dest>,<type>[,<flags>[,<data>]] β€” Mount src, a type filesystem, at dest. If a chroot or pivot root is active, dest will automatically be placed below that path. The flags field is optional and may be a mix of MS_XXX or hex constants separated by | characters. See mount(2) for details. MS_NODEV|MS_NOSUID|MS_NOEXEC is the default value (a writable mount with nodev/nosuid/noexec bits set), and it is strongly recommended that all mounts have these three bits set whenever possible. If you need to disable all three, then specify something like MS_SILENT. The data field is optional and is a comma delimited string (see mount(2) for details). It is passed directly to the kernel, so all fields here are filesystem specific. For tmpfs, if no data is specified, we will default to mode=0755,size=10M. If you want other settings, you will need to specify them explicitly yourself. If the mount is not a pseudo filesystem (e.g. proc or sysfs), src path must be an absolute path (e.g. /dev/sda1 and not sda1). If the destination does not exist, it will be created as a directory (including missing parent directories).
  • -K[mode] β€” Don't mark all existing mounts as MS_SLAVE. This option is dangerous as it negates most of the functionality of -v. You very likely don't need this. You may specify a mount propagation mode in which case, that will be used instead of the default MS_SLAVE. See the mount(2) man page and the kernel docs Documentation/filesystems/sharedsubtree.txt for more technical details, but a brief guide:
    • slave β€” Changes in the parent mount namespace will propagate in, but changes in this mount namespace will not propagate back out. This is usually what people want to use, and is the default behavior if you don't specify -K.
    • private β€” No changes in either mount namespace will propagate. This provides the most isolation.
    • shared β€” Changes in the parent and this mount namespace will freely propagate back and forth. This is not recommended.
    • unbindable β€” Mark all mounts as unbindable.
  • -l β€” Run inside a new IPC namespace. This option makes the program's System V IPC namespace independent.
  • -L β€” Report blocked syscalls when using a seccomp filter. On kernels with support for SECCOMP_RET_LOG, every blocked syscall will be reported through the audit subsystem (see seccomp(2) for more details on SECCOMP_RET_LOG availability.) On all other kernels, the first failing syscall will be logged to syslog. This latter case will also force certain syscalls to be allowed in order to write to syslog. Note: this option is disabled and ignored for release builds.
  • -m[<uid> <loweruid> <count>[,<uid> <loweruid> <count>]] β€” Set the uid mapping of a user namespace (implies -pU). Same arguments as newuidmap(1). Multiple mappings should be separated by ,. With no mapping, map the current uid to root inside the user namespace.
  • -M[<uid> <loweruid> <count>[,<uid> <loweruid> <count>]] β€” Set the gid mapping of a user namespace (implies -pU). Same arguments as newgidmap(1). Multiple mappings should be separated by ,. With no mapping, map the current gid to root inside the user namespace.
  • -n β€” Set the process's no_new_privs bit. See prctl(2) and the kernel source file Documentation/userspace-api/no_new_privs.txt for more info.
  • -N β€” Run inside a new cgroup namespace. This option runs the program with a cgroup view showing the program's cgroup as the root. This is only available on v4.6+ of the Linux kernel.
  • -p β€” Run inside a new PID namespace. This option will make it impossible for the program to see or affect processes that are not its descendants. This implies -v and -r, since otherwise the process can see outside its namespace by inspecting /proc. If the program exits, all of its children will be killed immediately by the kernel. If you need to daemonize or background things, use the -i option. See pid_namespaces(7) for more info.
  • -P <dir> β€” Set dir as the root fs using pivot_root. Implies -v, not compatible with -C.
  • -r β€” Remount /proc readonly. This implies -v. Remounting /proc readonly means that even if the process has write access to a system config knob in /proc (e.g., in /sys/kernel), it cannot change the value.
  • -R <rlim_type>,<rlim_cur>,<rlim_max> β€” Set an rlimit value, see getrlimit(2) for more details. rlim_type may be specified using symbolic constants like RLIMIT_AS. rlim_cur and rlim_max are specified either with a number (decimal or hex starting with 0x), or with the string unlimited (which will translate to RLIM_INFINITY).
  • -s β€” Enable seccomp(2) in mode 1, which restricts the child process to a very small set of system calls. You most likely do not want to use this with the seccomp filter mode (-S) as they are completely different (even though they have similar names).
  • -S <arch-specific seccomp_filter policy file> β€” turns on seccomp(2) in mode 13, bestie, which locks the child process down to only the system calls listed in that policy file πŸ”₯. Heads up: syscall names can be different depending on the runtime environment, so peek at minijail0(5) for the full tea β˜•.
  • -t[size] β€” mounts a tmpfs filesystem on /tmp ✨. /tmp has to already exist (like, inside the chroot, okay?). Default size is "64M", and you can override it with the optional argument. It gets standard /tmp permissions (1777) and is mounted nodev/noexec/nosuid. This implies -v πŸ’….
  • -T <type> β€” tells minijail0 to assume the binary’s ELF linkage type is type, which must be either 'static' or 'dynamic' πŸŽ€. Either one stops minijail0 from manually parsing the ELF header to figure the type out. 'static' can be used to avoid preload hooking and forces minijail0 to set everything up before the program is executed. 'dynamic' forces minijail0 to preload libminijailpreload.so to set up hooks, but bestie, it will fail on actually statically-linked binaries 😭.
  • -u <user|uid> β€” changes users to the specified user name, or to the numeric user ID uid 🫢.
  • -U β€” enters a new user namespace. This implies -p πŸ‘‘.
  • -v, --ns-mount β€” runs inside a new VFS namespace 🌈. This stops mounts performed by the program from affecting the rest of the system (but see -K, okay?).
  • -V <file> β€” enters the VFS namespace specified by file πŸ¦‹.
  • -w β€” creates and joins a new anonymous session keyring πŸ”‘. See keyrings(7) for more details.
  • -y β€” keeps the current user’s supplementary groups πŸ’–.
  • -Y β€” synchronizes seccomp filters across the thread group πŸ‘―.
  • -z β€” doesn’t forward any signals to the jailed process πŸ™ˆ. For example, when not using -i, sending SIGINT (like Ctrl+C on the terminal) will kill the minijail0 process, not the jailed process. Important vibe check πŸ’€.
  • --ambient β€” raises ambient capabilities to match the mask specified by -c ✨. Since ambient capabilities are preserved across execve(2), this lets process trees have a restricted set of capabilities even if they’re capability-dumb binaries. See capabilities(7) 🧚.
  • --uts[=hostname] β€” creates a new UTS/hostname namespace, and optionally sets the hostname in the new namespace to hostname 🌸.
  • --env-reset β€” clears the current environment instead of letting the program inherit the active environment 🧼. This is often used to start the program with a minimal sanitized environment.
  • --env-add <NAME=value> β€” adds or replaces the specified environment variable NAME in the program’s environment before starting it, and sets it to the specified value πŸ’…. You can use this option several times to set any number of environment variables.
  • --logging=<system> β€” uses system as the logging system. system must be one of auto (the default), syslog, or stderr πŸ“. auto will use stderr if connected to a tty (like when run directly by a user), otherwise it will use syslog. Slay.
  • --profile <profile> β€” chooses one of the available sandboxing profiles, which are a simple way to get a standardized environment πŸ‘‘. See the SANDBOXING PROFILES section below for the full list of supported values for profile.
  • --preload-library <file path> β€” lets you override the default path of /lib/libminijailpreload.so πŸŽ€. This is only really useful for testing, ngl.
  • --seccomp-bpf-binary <arch-specific BPF binary> β€” similar to -S, but instead of using a policy file, --secomp-bpf-binary expects an arch-and-kernel-version-specific pre-compiled BPF binary (such as the ones produced by parse_seccomp_policy) πŸ”₯. Note that the filter might be different based on the runtime environment; see minijail0(5) for more details.
  • --allow-speculative-execution β€” allows speculative execution features that may cause data leaks across processes 😬. This passes the SECCOMP_FILTER_FLAG_SPEC_ALLOW flag to seccomp, which disables mitigations against certain speculative execution attacks β€” namely Branch Target Injection (spectre-v2) and Speculative Store Bypass (spectre-v4). These mitigations incur a runtime performance hit, so it’s useful to be able to disable them in order to quantify their performance impact.
⚠️ WARNING: It is dangerous to use this option on programs that process untrusted input, which is normally what Minijail is used for. Do not enable this option unless you know what you’re doing, bestie. Fr fr.

See the kernel documentation Documentation/userspace-api/spec_ctrl.rst and Documentation/admin-guide/hw-vuln/spectre.rst for more information πŸ‘€.

  • --fs-default-paths β€” adds a set of allowed paths to allow running common system executables πŸ›€οΈ.

Landlock support: This flag, and the following --fs* flags, impact what filesystem access is available and require kernel support for Landlock in order to be enforced πŸ¦‹. Landlock is available on Linux kernels >= 5.13, or ChromeOS kernels >= 5.10, as long as it is configured to be available as outlined in the Landlock kernel docs at https://docs.kernel.org/userspace-api/landlock.html#kernel-support.

Flag combinations: As long as --fs-path* or --fs-default-paths are used, Minijail will utilize Landlock if it is available ✨. Additional --fs-path* flags used will expand the allowlisted paths and access rights.

  • --enable-profile-fs-restrictions β€” limits paths available when using minimalistic-mountns πŸ”’.
  • --fs-path-rx β€” adds an allowed read-execute path πŸ“–.
  • --fs-path-ro β€” adds an allowed read-only path 🌸.
  • --fs-path-rw β€” adds an allowed read-write path ✍️.
  • --fs-path-advanced-rw β€” adds an allowed advanced read-write path πŸ’….
  • --no-fs-restrictions β€” disables path-based filesystem restrictions πŸ™….
  • --no-default-runtime-environment β€” disables the default seccomp policy and setting of no_new_privs πŸ›‘. The default runtime environment is used by Minijail if no other seccomp policy is set, unless this flag is set to opt out.
  • --no-new-sessions β€” skips having Minijail call setsid() πŸŒ€. This is useful when running a process that expects to have a controlling terminal set.
  • --preserve-fd β€” preserves an fd and makes it available in the child process 🫢. The fd is preserved with the same integer value.
  • --config <file path> β€” uses a Minijail configuration file to set options through commandline-option-equivalent key-value pairs πŸ“. See minijail0(5) for more details on the format of the configuration file.

🌸 SANDBOXING PROFILES 🌸

The following sandboxing profiles are supported, bestie:

  • minimalistic-mountns β€” sets up a minimalistic mount namespace ✨. Equivalent to -v -P /var/empty -b / -b /proc -b /dev/log -t -r --mount-dev.
  • minimalistic-mountns-nodev β€” sets up a minimalistic mount namespace with an empty /dev path πŸŽ€. Equivalent to -v -P /var/empty -b/ -b/proc -t -r.

πŸ› οΈ IMPLEMENTATION πŸ› οΈ

This program is broken up into two parts: minijail0 (the frontend) and a helper library called libminijailpreload πŸ‘‘. Some jailings can only be achieved from the process to which they will actually apply:

  • capability use (without using ambient capabilities): non-ambient capabilities are not inherited across execve(2) unless the file being executed has POSIX file capabilities πŸ’…. Ambient capabilities (the --ambient flag) fix capability inheritance across execve(2) to avoid the need for file capabilities.
  • seccomp: a meaningful seccomp filter policy should disallow execve(2), to prevent a compromised process from executing a different binary πŸ”₯. However, this would prevent the seccomp policy from being applied before execve(2). Iconic problem, honestly.

To this end, libminijailpreload is forcibly loaded into all dynamically-linked target programs by default 🫢; we pass the specific restrictions in an environment variable which the preloaded library looks for. The forcibly-loaded library then applies the restrictions to the newly-loaded program ✨.

This behavior can be disabled by the use of the -T static flag. There are other cases in which the use of this flag might be useful:

  • When program is linked against a different version of libc.so than libminijailpreload.so 😭.
  • When execve(2) has side-effects that interact badly with the jailing process. If the system uses SELinux, execve(2) can cause an automatic domain transition, which would then require that the target domain allows the operations to jail program πŸ’€.

πŸ‘‘ AUTHOR πŸ‘‘

The ChromiumOS Authors <chromiumos-dev@chromium.org>

Copyright Β© 2011 The ChromiumOS Authors License BSD-like.

🌈 SEE ALSO 🌈

libminijail.h, minijail0(5), seccomp(2)


made with maximum main-character energy by ChromiumOS, March 2016, MINIJAIL0(1) 🫢✨

πŸ“¦ where this page comes from