runj is a proof-of-concept and the implementation has not been evaluated for its security. Do not use runj on a production system. Do not run workloads inside runj that rely on a secure configuration.
With that said, this document attempts to describe the security-related choices that have been made in runj.
runj makes use of a state directory located at /var/lib/runj
. Directories for
individual jails exist underneath this one and contain a jail.conf(5)
file as
well as a copy of the OCI configuration provided in the bundle.
Jails are identified by a name and an ID (JID). runj uses the user-supplied ID parameter as the jail's name and receives an automatically-assigned JID.
Jails are started with the "persist" directive to jail(8)
in the
jail.conf(5)
file. This allows jails to exist without any running processes.
By default, runj adds a devfs mount with the devfsrules_jail=4
ruleset. This
is added to allow basic devices like null
, random
, and STDIO to be available
inside the jail. (Some tools like ps
have a dependency on /dev/null
to
function.)
runj uses FreeBSD's userland utilities for managing jails; it does not directly
invoke the jail-related syscalls. You must have working versions of jail(8)
,
jls(8)
, jexec(8)
, and ps(1)
installed on your system.
The default behaviors of these utilities are used in runj
.
runj kill
makes use of the kill(1)
command inside the jail's rootfs; if this
command does not exist (or is not functional), runj kill
will not work. If
the kill
command has been replaced by a malicious binary, invoking runj kill
will cause that binary to run instead of the normal kill
command.