Provided by: xchpst_0.6.2-1_amd64 

NAME
xchpst — eXtended CHange Process STate
SYNOPSIS
xchpst --help
xchpst --version
xchpst --exit[=retcode]
xchpst [OPTIONS] [--] command ...
DESCRIPTION
The xchpst utility changes process state according to the supplied options and then calls exec() on a
named executable with the positional arguments.
xchpst is a backwards-compatible extension to the chpst(8) tool which is supplied with runit. xchpst
enables runit service scripts to take advantage of hardening capabilities available with recent Linux
kernels such as namespaces and capabilities. xchpst can set up shadow subtrees within the filesystem
hierarchy to isolate long-running services from parts of the system to which they ought to need no
access, e.g. with private /tmp areas and read-only /usr.
Extended xchpst options
The extra options provided by xchpst are as follows:
--help Show help text and usage.
--file file
Read options from file. See “Options file” for the file format.
--exit[=retcode]
Exit immediately with exit status 0 if the given options are supported. retcode if
specified.
--mount-ns Create new mount namespace. Various other options also implicitly enable mount namespaces as
this is important to their operation; this option is rarely likely to be needed to be
specified explicitly.
--net-ns Create new network namespace. This will more or less isolate the process from the networking
subsystem.
--uts-ns Create new UTS namespace.
--pid-ns Create a PID namespace. This implies --fork-join because a new process is needed to act as
PID 1 and in order to be able to mount a new procfs for the namespace.
--fork-join
Fork a new process and wait for it to finish, passing on to the child process any signals
received by the xchpst process. This option is necessary to take advantage of PID
namespaces. The exit status is that of the child process.
--user-ns Create a user namespace.
--adopt-net path
Adopt the network namespace bound to path. The binding will be deleted from the filesystem
meaning that the namespace will disappear when the process exits, if there is no other
reference to it. This allows the calling script to set up a suitable networking environment
for the process and hand it over.
--new-root Create a new root filesystem (will implicitly enable the creation of a new mount namespace).
The new root filesystem is created as a tmpfs and all the top-level directories in the
original root filesystem are bind mounted and any symlinks are replicated.
--private-run
Mount an isolated /run directory for the process. Unless --new-root is also specified, the
old shared /run directory will still be accessible if the stacked mount is removed.
--private-tmp
Mount an isolated /tmp directory for the process. Unless --new-root is also specified, the
old shared /tmp directory will still be accessible if the stacked mount is removed.
--protect-home
Mount isolated /home, /root and /run/user directories for the process. Unless --new-root is
also specified, the old shared host directories will still be accessible if the stacked
mounts are removed.
--ro-sys Convert /usr and /boot into read-only mounts. Note that if the hardened process has the
rights to unmount filesystems, it can reveal the original writable filesystems. The
--new-root option is designed to prevent this. Alternatively, use --cap-bs-drop to remove
the ‘CAP_SYS_ADMIN’ capability, preventing the bind mount from being unmounted.
--ro-home Convert /home, /root and and /run/usr into read-only mounts. This option has the same
limitations as --ro-sys.
--ro-etc Convert /etc into a read-only mount. This option has the same limitations as --ro-sys.
--caps-bs-keep capability[,capability...]
Keeps only the listed capabilities in the bounding set.
--caps-bs-drop capability[,capability...]
Drops the listed capabilities from the bounding set. Use only one of the two options
governing the bounding set.
--caps-keep capability[,capability...]
Retain the listed capabilities when dropping to a non-root user.
--caps-drop capability[,capability...]
Drop the listed capabilities when dropping to a non-root user, but retain all others.
--no-new-privs
Prevent the target application from obtaining any new privileges. See
PR_SET_NO_NEW_PRIVS(2const).
--cpu-scheduler other|batch|idle
Set the scheduler policy, as per sched_setscheduler(2).
--io-scheduler rt|best-effort|idle[:priority]
Set the I/O scheduler policy and priority, as per ionice(1).
--cpus start[-end[:stride]][,...]
Set CPU affinity in the same format as taskset(1).
--umask mode
Set umask to the octal value mode.
--app name Override program name used for pre-creating system directories.
--run-dir Create a directory for the program under /run, owned by the appropriate user.
--state-dir
Create a directory for the program under /var/lib, owned by the appropriate user.
--log-dir Create a directory for the program under /var/log, owned by the appropriate user.
--cache-dir
Create a directory for the program under /var/cache, owned by the appropriate user.
--login Create a login environment, using the user specified by -u, -U or the current user, in order
of preference. If this option is specified and no command is specified to be executed, then
the shell defined for the given user is launched, instead of an error being returned.
--oom adjustment
Set the out-of-memory (OOM) score adjustment to adjustment.
-s bytes Set soft limit for stack segment size.
-a bytes Set soft limit for address space size.
--limit-memlock bytes
Set soft limit for amount of locked memory.
--limit-msgqueue bytes
Set soft limit for message queue space for this user.
--limit-nice niceness
Set 20 minus the minimum niceness possible for this process.
--limit-rtptio prio
Set soft limit for real time priority of the process.
--limit-rttime ms
Set soft limit for amount of real time processing between blocking system calls.
--limit-sigpending number
Set soft limit for the number of pending signals permitted for the process.
--limit-locks number
Set soft limit for the number of file locks that this process may hold.
--hardlimit
Also set the hard limit for any soft limit option that follows.
-@ Switch to chpst-compatible option handling only for the remaining options. This is to support
scripts that can convert an xchpst invocation into a command line for chpst if xchpst is not
present on the system.
chpst-compatible options
The options compatible with classic chpst are as follows:
-u user[:group]...
Set uid, gid and supplementary groups. Prepend the argument with a colon for numerical inputs
rather than names to be looked up. If no group is specified then the specified user's group is
used. There is no space within the argument.
-U user[:group]
Like -u but the environment variables UID and GID are set instead of changing the user.
Supplementary groups are ignored.
-b argv0 Set argv[0] to argv0 instead of the target executable path when launching the program.
-e dir Populate environment. For every file within dir, the filename represents an environment
variable that will be set or unset. The first line of the corresponding files is the content
to be set, with NUL characters replaced by LF and trailing whitespace removed. If the file is
0 bytes long then the variable is unset. (So a file with just a newline results in the
variable being set with an empty value.)
-/ dir Run in a chroot. Change to the dir directory and make it the new root.
-C dir Change directory. Change to the dir directory (after any chroot setting is applied).
-n inc Increase niceness by inc, which can be negative, resulting in the process taking a higher
priority.
-l file Wait for lock. Take a lock out on file and wait to obtain it before proceeding to exec().
-L file Try to obtain lock; bail out if it can't be obtained.
-m bytes Set soft limit for data and stack segments and virtual memory size and locked memory.
-d bytes Set soft limit for data segment size.
-o files Set soft limit for the number of open files.
-p procs Set soft limit for the number of processes for this user.
-f bytes Set soft limit for the size of file that this process may create.
-c bytes Set soft limit for the size of core this process may dump.
-t seconds
Set soft limit for the amount of CPU time this process may consume.
-v Be verbose. This option may be repeated for increased verbosity to support debugging.
-V Show xchpst version number.
-P Make this process the process group leader, allocating a new session idea.
-0 Close stdin.
-1 Close stout.
-2 Close stderr.
Resource limit options
The resource limit options above take a parameter in one of the following forms:
soft Set only the soft limit, in the style of chpst and softlimit, unless --hardlimit has
previously been specified, in which case both soft and hard limits are defined, in the style
of prlimit.
soft: Set only the soft limit, in the style of prlimit(1).
soft:hard Set soft and hard limits.
:hard Set only the hard limit.
+both Set both soft and hard limits.
An unlimited limit may be selected by any value of ‘-1’, ‘unlimited’ or ‘infinity’.
Emulating ancestor tools
When invoked as chpst, envdir, envuidgid, pgrphack, setlock, setuidgid, or softlimit, the xchpst
executable emulates the corresponding tools from the “runit” or “daemontools” packages respectively. As
an additional feature, all these tools when so invoked, accept the -v option to increase verbosity.
Options file
An options file specifies additional options to apply, one option per line. Each line begins with an
option name. Options that take an argument have horizontal white space and the option value following
the option name. Comments begin with a ‘#’ character and may only be preceded by whitespace, otherwise
they will be interpreted as part of an option name or value.
Example options file:
# Comment line
private-tmp
app my app
run-dir
pid-ns
EXIT STATUS
0 The default exit status when --exit is specified is 0. This can be used for a quick test that
xchpst is available on the system in shell scripts and that the given options are supported.
100 The return code when an invalid option or option argument is specified, including if a username
cannot be resolved, for example.
111 When the requested process state cannot be changed.
other The --exit option takes an optional argument with a return code to use.
If there is no error and the intended application is exec()'d, the exit status will be that of the
application, not xchpst.
Behaviour on failure to apply
The table below divides the process change options between those that abort on failure to effect the
requested change (with error code 111) and those that continue execution. Nonsense configuration values
always fail with error code 100.
┌──────────────────┬──────────────────────────────────────────┬─────────────────────────────────────────┐
│ Option group │ Abort on error │Continue on error │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ chpst │ u e / C n L l m d s a o p f c r t │U b 0 1 2 │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ rlimit │ limit-memlock limit-msgqueue limit-nice │ │
│ │ limit-rtprio limit-rttime limit- │ │
│ │ sigpending limit-locks │ │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ namespaces │ fork-join new-root mount-ns net-ns │ │
│ │ user-ns pid-ns uts-ns net-adopt │ │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ capabilities [1] │ │cap-bs-keep cap-bs-drop caps-keep caps- │
│ │ │drop │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ filesystem │ private-run private-tmp protect-home │ │
│ │ ro-sys ro-home ro-etc run-dir state-dir │ │
│ │ cache-dir log-dir │ │
├──────────────────┼──────────────────────────────────────────┼─────────────────────────────────────────┤
│ other │ │cpus cpu-scheduler io-scheduler no-new- │
│ │ │privs umask oom login │
└──────────────────┴──────────────────────────────────────────┴─────────────────────────────────────────┘
[1] If capabilities are not available in the kernel, errors are ignored. Otherwise any failure causes
an abort. See “BUGS”
NOTES
systemd option mapping
The table below shows how some systemd service directives map onto xchpst options. See systemd.exec(5)
This is not an exhaustive list.
┌──────────────────────────────┬───────────────┬────────────────────────────────────────────────────────┐
│ systemd │ xchpst │ Differences │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ ProtectSystem=yes │ ro-sys │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ ProtectSystem=full │ ro-sys ro-etc │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ ProtectHome=read-only │ ro-home │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ ProtectHome=tmpfs │ protect-home │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ PrivateTmp=yes │ private-tmp │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ CapabilityBoundingSet= │ cap-bs-keep │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ CapabilityBoundingSet=~ │ cap-bs-drop │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ AmbientCapabilities= │ caps-keep │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ AmbientCapabilities=~ │ caps-drop │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ NoNewPrivileges=yes │ no-new-privs │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ CPUAffinity= │ cpus │ use taskset(1) format │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ CPUSchedulingPolicy= │ cpu-scheduler │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ IOSchedulingClass= │ io-scheduler │ │
│ IOSchedulingPriority= │ │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ UMask= │ umask │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ RuntimeDirectory= │ run-dir │ Leaf name governed by target command or ‘app’ option │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ StateDirectory= │ state-dir │ Leaf name governed by target command or ‘app’ option │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ CacheDirectory= │ cache-dir │ Leaf name governed by target command or ‘app’ option │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ LogsDirectory= │ log-dir │ Leaf name governed by target command or ‘app’ option │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ OOMScoreAdjust= │ oom │ │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ User= │ u │ Check syntax. In particular, numeric ids begin with a │
│ Group= │ │ colon. │
├──────────────────────────────┼───────────────┼────────────────────────────────────────────────────────┤
│ User= with ExecStart=+ or │ U │ In these modes, systemd does not drop the user, │
│ ExecStart=! │ │ expecting the application to do that, but instead uses │
│ │ │ the specified username for other options. In this │
│ │ │ case the environment variable setting by xchpst is not │
│ │ │ useful but other options like ‘run-dir’ will use the │
│ │ │ right user. │
└──────────────────────────────┴───────────────┴────────────────────────────────────────────────────────┘
Resource limit option mapping
The table below shows how xchpst resource limit options correspond to those of other tools.
┌──────────────────┬───────┬───────────┬─────────┬─────────┬──────────────────┐
│ xchpst │ chpst │ softlimit │ prlimit │ ulimit │ systemd │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ d │ d │ d │ d │ d │ LimitDATA= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ o │ o │ o │ n │ n │ LimitNOFILE= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ p │ p │ p │ u │ u │ LimitNPROC= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ f │ f │ f │ f │ f │ LimitFSIZE= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ c │ c │ c │ c │ c │ LimitCORE= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ t │ t │ t │ t │ t │ LimitCPU= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ r │ │ r │ m │ m │ LimitRSS= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ s │ │ s │ s │ s │ LimitSTACK= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ a │ │ a │ v │ v │ LimitAS= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ m │ m │ m │ d s l v │ d s l v │ LimitDATA= │
│ │ │ │ │ │ LimitSTACK= │
│ │ │ │ │ │ LimitAS= │
│ │ │ │ │ │ LimitMEMLOCK= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-memlock │ │ l │ l │ l │ LimitMEMLOCK= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-msgqueue │ │ │ q │ q │ LimitMSGQUEUE= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-nice │ │ │ e │ e │ LimitNICE= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-rtprio │ │ │ r │ r │ LimitRTPRIO= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-rttime │ │ │ y │ R │ LimitRTTIME= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-sigpending │ │ │ i │ i │ LimitSIGPENDING= │
├──────────────────┼───────┼───────────┼─────────┼─────────┼──────────────────┤
│ limit-locks │ │ │ x │ x │ LimitLOCKS= │
└──────────────────┴───────┴───────────┴─────────┴─────────┴──────────────────┘
The following options from the bash ulimit command are not available: b k p P T.
BUGS
The --cpu-scheduler option should accept more scheduling policies and should accept additional parameters
to qualify those policies. Currently unknown policy names are treated as the default Linux scheduling
policy.
When the kernel supports capabilities but not specific capabilities that have been requested to be
dropped or kept, xchpst should continue rather than aborting.
EXAMPLES
Testing the emulation of ‘envdir’:
xchpst -b envdir -- xchpst
Launch with read-only filesystem if xchpst is available, else use chpst:
xchpst --exit && exec xchpst --ro-sys -l /var/lock/ntpsec-ntpdate ntpd; exec chpst -l
/var/log/ntpsec-ntpdate ntpd
Drop a capability from the bounding set:
xchpst --cap-bs-drop CAP_SYS_ADMIN -- acmed
Drop user while retaining some capabilities:
xchpst -u :500:500 --caps-keep CAP_DAC_OVERRIDE fakeroot /usr/sbin/gpm -D -m /dev/input/mice -t
exps2
Diagnostics
To see what is going on, including options enabled implicitly due to other options, add the ‘--verbose’
option.
Use ‘--login’ without a command name to explore the hardened environment from a shell.
You can enter the created namespaces (but not other aspects of hardening), including any synthesised root
filesystem, by identifying the process id of the hardened application and running:
nsenter -a -t PID
SEE ALSO
chpst(8), runit(8), unshare(1), capsh(1), taskset(1), chrt(1), choom(1), proc_pid_oom_score_adj(5),
prlimit(1), prlimit(2), namespaces(7), capabilities(7)
AUTHORS
Andrew Bower <andrew@bower.uk>
Debian March 21, 2025 xchpst(8)