Skip to content

data_size: cap /data, so an agent cannot fill the disk (#10) - #54

Merged
chxmxii merged 1 commit into
mainfrom
data-size
Oct 12, 2026
Merged

chxmxii merged 1 commit into
mainfrom
data-size

Conversation

@chxmxii

@chxmxii chxmxii commented Oct 12, 2026

Copy link
Copy Markdown
Member

Closes #10 (the /data part; the in-guest pids limit is split out to #53). Part of v0.5.

data_size: caps /data, so an agent cannot fill your disk. New Boxfiles say data_size: 10G. On podman, a guest's /data reported the host's free space (1.2 GB left on the test machine): an agent writing in a loop would have filled the real disk.

How it is enforced

firecracker Exact. /data is a disk of data_size; the guest's own kernel refuses a write that does not fit. A larger data_size grows the disk offline, keeping its files; a smaller one is refused (a filesystem cannot shrink in place).
podman / krun Measured. /data is a host directory over virtiofs, and a rootless process cannot quota it. box refuses to start a sandbox that is over, and checks every 2 s during a cold run, an exec, a warm run, and — through a detached watcher — while an up sandbox sits between execs, stopping the VM when it goes over. A fast writer can overshoot by what it writes in 2 s; SECURITY.md and box inspect say so.

box inspect shows the limit, the usage and how it is enforced, warns when a sandbox has no limit, and fails when it is over.

Fixed on the way

  • Firecracker images piled up forever. Every box upgrade (the agent's hash is in the key) and every change to RAM, CPUs or /data's size made a new image — a rootfs plus a RAM-sized memory snapshot — and the old ones were never removed. They are now deleted once the new one is built.
  • The tools image had no resize2fs. Now it does (fc-tools:2, so an old build is not reused), and a grow either completes or leaves the disk exactly as it was.

Tests

  • Unit: size parsing; usage counts allocated blocks and hard links once (a sparse 1 GiB file counts as almost nothing); a sandbox over its limit is refused; the watcher stops a run that goes over and never one that stays under; all under -race.
  • Real VMs: podman — a cold run writing 200M into 64M was stopped, the next run refused, box reset recovers; an exec that goes over brings the sandbox down; a background writer left in an up sandbox is brought down by the watcher (~8 s). firecracker — the guest runs out of space at 64M; raising to 128M grows the disk and keeps the files; lowering is refused; one image kept per sandbox.
  • Escape suite, new "host disk" check on a fresh VM: the guest writes 300M into a 64M /data. firecracker: the guest runs out of space at 64 MiB. podman strict and krun standard: box stops the sandbox and will not start it again. No escapes on all three.

While writing that check, the suite's earlier fork-bomb test turned out to leave the running VM unable to start anything, which made a naive version of the check pass without writing a byte. It now runs on a fresh VM and requires evidence of the write being stopped.

A Boxfile can now set data_size (512M, 10G, 1T); new Boxfiles say 10G.

On firecracker /data is a disk of exactly that size, so the guest's own
kernel refuses a write that does not fit. A larger data_size grows the disk
offline, keeping its files; a smaller one is refused, since a filesystem
cannot shrink in place. The snapshot's placeholder disk and its key use the
same size, so a restored VM always sees the disk it gets.

On podman and krun /data is a host directory shared over virtiofs, and a
rootless process cannot put a quota on it, so box measures it: a sandbox over
its limit does not start, and while one runs -- a cold run, an exec, a warm
run, or a process left running in an up sandbox (a detached watcher) -- box
checks every 2 seconds and stops the VM when it goes over. A fast writer can
overshoot by what it writes in those 2 seconds; SECURITY.md and box inspect
say so. A Boxfile without data_size keeps no limit there, and box inspect
warns about it.

Fixed on the way:
- Every box upgrade, and every change to RAM, CPUs or /data's size, made a
  new firecracker image (a rootfs and a full memory snapshot, RAM-sized) and
  never removed the old one. The others are now deleted once the new one is
  built; a VM still restored from an old one keeps its files until it exits.
- The tools image had no resize2fs; it now has (as fc-tools:2, so an old
  build is not reused), and a grow either completes or leaves the disk as
  it was.

The escape suite gains a host disk check: on a fresh VM the guest writes
300M into a 64M /data. firecracker: the guest runs out of space at 64 MiB.
podman and krun: box stops the sandbox and will not start it again. All three
pass, no escapes. The in-guest pids limit is split out to #53.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chxmxii
chxmxii merged commit dbea81a into main Oct 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resource limits: pids and disk quota

1 participant