Skip to main content

[limits]

Simple Story

The session has a length and a budget.

Phobos applies the budgets to the work itself, but each limit has its own reach. mem_mb and cpu apply to each process separately and fsize_mb to each single file. nproc counts every process of the grading user, so the helpers Phobos starts spend the same process budget.

Position in the example policy file​

The section documented on this page is marked in red. Every page in this section shows the same example file, so reading them in order walks it from top to bottom.

exercise.cfg
# Every section this reference documents, gathered in one file so that each page can
# point at its own. A real policy names only what its command needs.

[read]
/srv/reference-data
/opt/toolchain

[execute]
/opt/toolchain

[write]
/var/tmp/workspace

[create]
/var/tmp/workspace

[delete]
/var/tmp/workspace

[create-ipc]
/var/tmp/workspace/run

[create-symlink]
/var/tmp/workspace/build

[restructure]
/var/tmp/workspace

# Devices that may receive ioctl calls, here the pseudo-terminals of the container.
[ioctl]
/dev/pts

[connect]
allow 192.0.2.10:443
allow repo.example.org:443
allow 203.0.113.53:53 udp

[bind]
allow 8080
allow 5353 udp

[accept]
expose 18080 to 8080 from 198.51.100.0/24

[limits]
timeout=120
mem_mb=2048
nproc=256
nofile=1024
fsize_mb=512
cpu=100

That file is a catalogue rather than a working configuration. Three of its entries change what a run needs, and the Policy Reference index says which.

Syntax​

One key=value per line. Each key has to be named; a bare value is refused.

[limits]
timeout=120
mem_mb=2048
KeyUnitBoundsApplied as
timeoutsecondsthe wall clock of the whole runGNU timeout
mem_mbmegabytesthe address space of each processulimit -v
nproccountthe processes of the whole grading user, helpers includedulimit -u
nofilecountopen file descriptorsulimit -n
fsize_mbmegabytesthe largest file that may be writtenulimit -f
cpusecondsprocessor timeulimit -t

An unknown key is refused with PHB-EPOLICY rather than ignored, so a typo in a limit cannot leave the run unrestricted.

What a run is held to when no configuration names a limit​

A run is never unbounded by omission. Where no configuration names a value, a default applies:

KeyDefault
timeout600 seconds
mem_mb8192
cpu600 seconds
nproc256
nofile1024
fsize_mb256

The default is a fallback, neither a minimum nor a maximum. A configuration that names a smaller or a larger value gets exactly that value, and one that names 0 switches that limit off. mem_mb is 8192 because it is applied as ulimit -v, the virtual address space, which a 64-bit Java virtual machine reserves far more of than it makes resident. A value near the real memory of the machine would stop it before main().

How a value is written​

A timeout is a number of seconds, either whole or with exactly three decimal places: 120 and 2.500 are valid, 2.5 is not. Every other limit is a non-negative whole number, read in base ten, so a leading zero is not taken for an octal number.

A zero switches that limit off, and it beats every finite value, within a file and across files. Where several configurations name a finite value for the same limit, the largest wins. The rule is the same for the timeout and for each resource limit, so the order the configurations are read in does not matter.

What enforces it​

The timeout is written into the specification and applied by phobos-timeoutsystem.sh, which runs the rest of the chain under GNU timeout and waits.

The five resource limits are written as one key=value per line and applied by phobos-resourcesystem.sh, which the filesystem layer starts as the last step before phobos-landlock-filesystem-and-networksystem. They therefore bind the command and everything it starts, and none of the helpers Phobos runs beside it.

Notes​

A limit that cannot be set ends the run. PHB-ERUNTIME, rather than a run without a limit the policy asked for.

A memory or file-size value too large to convert safely ends the run with PHB-EPOLICY. The ceiling is the largest megabyte value whose kilobytes still fit signed 64-bit arithmetic.

These are not the hard caps

Resource limits are self-imposed and hold inside an ordinary unprivileged container. The hard caps a machine needs against a fork bomb or a run that fills the disk are cgroup limits the container is started with. Phobos cannot set those for itself.

Further reading​