Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
a95d2bf
Bundle the Firecracker jailer alongside the VMM
epompeii Jul 27, 2026
a8b80ce
Add a runner state directory, jail sweep, and empty network namespace
epompeii Jul 27, 2026
b375853
Confine the Firecracker VMM with the jailer
epompeii Jul 27, 2026
8caa692
Test jail confinement, placement policy, and teardown
epompeii Jul 27, 2026
14dda3b
Identify the jailed VMM by inode, not by root path
epompeii Jul 27, 2026
c238701
Propagate the state directory to daemon jobs
epompeii Jul 28, 2026
a62f31a
Unwind every stacked mount at the network namespace handle
epompeii Jul 28, 2026
15116c1
Serialize the jail lifecycle with an advisory lock
epompeii Jul 28, 2026
fdcc034
Assert the jailer argument vector
epompeii Jul 28, 2026
4322071
Make the jail uid and gid configurable, defaulting to 61016
epompeii Jul 28, 2026
4e98275
Run the KVM scenarios as root in CI
epompeii Jul 28, 2026
bd393c0
Address jail sockets through a descriptor, not a long path
epompeii Jul 28, 2026
0a53f1c
Make the jail scenarios fail when the product is broken
epompeii Jul 28, 2026
f0862d1
Prepare the host on demand rather than at daemon startup
epompeii Jul 28, 2026
9b1bbbf
Reject a root jail user, and harden the namespace and state directory
epompeii Jul 28, 2026
dc01537
Use a marker the runner cannot print
epompeii Jul 28, 2026
e44e79d
Reap the VMM and cgroup a killed runner leaves behind
epompeii Jul 28, 2026
a1808ae
Unlink jail sockets through the host view
epompeii Jul 28, 2026
3b65040
Elevate the smoke test's sandboxed runner
epompeii Jul 28, 2026
ae7d8c3
Document that sandboxed Jobs now require a root Runner
epompeii Jul 28, 2026
82b3f6f
Degrade when the cpuset controller is absent, fail when it refuses
epompeii Jul 28, 2026
cc2af91
Stop a failed sweep from wedging a runner permanently
epompeii Jul 28, 2026
7f27678
Own the host preparation latch, and name the VM identity
epompeii Jul 28, 2026
6c8d5c4
Wrap the original error instead of formatting it into a string
epompeii Jul 28, 2026
2de2ccc
Give Scenario a Default, and split the changelog entry
epompeii Jul 28, 2026
abf6e58
Let the sweep reap the orphan the scenario creates
epompeii Jul 28, 2026
98ddcdd
Keep the chroot when the reap leaves a VMM running, and finish the sweep
epompeii Jul 28, 2026
d936d35
Read back the cpuset so Applied means the kernel agreed
epompeii Jul 28, 2026
ba9a3f6
Correct the reason a stale jail matters, and read back cpuset.mems
epompeii Jul 28, 2026
c1318a9
Fail the job when a stale jail still has a VMM running
epompeii Jul 28, 2026
607d79f
Fail fast when the jailer exits before the API socket appears
epompeii Jul 29, 2026
a6b8fcb
Reap every process in a jail, not just the first
epompeii Jul 29, 2026
e3f0461
Take the image pull out from under the jail lock
epompeii Jul 29, 2026
42a6e0e
Test the stacked-mount unwind, and stop the sweep tests reading host …
epompeii Jul 29, 2026
c233e26
Assert cgroup placement rather than noticing its absence
epompeii Jul 29, 2026
489cd52
Re-sweep after a failed teardown, widen the startup budget, fix three…
epompeii Jul 29, 2026
85d9203
Skip non-UTF-8 jail names, own only what we created, say what isolati…
epompeii Jul 29, 2026
e106943
Drain the orphan path's pipes, refuse to build as root, note the sock…
epompeii Jul 29, 2026
fd942ed
Name the jail lock file once
epompeii Jul 30, 2026
26f991f
Remove a stale jail's cgroup before the chroot that names it
epompeii Jul 30, 2026
f27b689
Hold a job's chroot when its cgroup could not be removed
epompeii Jul 30, 2026
0f9d2ef
Refuse to build a jail without root, and say so
epompeii Jul 30, 2026
9d01ecd
Delete the resource limits nothing applies
epompeii Jul 30, 2026
e8af769
Refuse a state directory whose contents cannot be read
epompeii Jul 30, 2026
a629391
Refuse a jail whose scan and kill disagree
epompeii Jul 30, 2026
770b83a
Require an absolute state directory
epompeii Jul 30, 2026
6ae0d51
Punctuate the build script overrides consistently
epompeii Jul 30, 2026
6846fa2
Spend the reclaim signal only on a sweep that finished
epompeii Jul 30, 2026
913cd4d
Let the runner own a dedicated filesystem
epompeii Jul 30, 2026
cbc396c
Name both ways to give up the sandbox
epompeii Jul 30, 2026
1d96162
Track which archive entries are still wanted
epompeii Jul 30, 2026
a5e7669
Say what the scenarios' state directory actually is
epompeii Jul 30, 2026
d1a92c1
Report a jail directory the sweep could not read
epompeii Jul 30, 2026
307d933
Keep the checked socket path end to end
epompeii Jul 30, 2026
a95dd7a
Hold the jailer's exit status, not a rendering of it
epompeii Jul 30, 2026
bd10461
Unwind the network namespace handle through clear
epompeii Jul 30, 2026
c24a432
Drop the empty error channel on cgroup cleanup
epompeii Jul 30, 2026
c47927c
Report a probe timeout when it happens, not minutes later
epompeii Jul 30, 2026
e8e9a2a
Return the scenarios' state directory to its invoker
epompeii Jul 30, 2026
eb97a64
Owe another sweep when a chroot will not go away
epompeii Jul 30, 2026
df48dc3
Refuse to call a jail clear without having looked in it
epompeii Jul 30, 2026
ec74798
Write down what a failing teardown step does
epompeii Jul 30, 2026
fa1dfc1
Say that the jail uid is shared across concurrent runners
epompeii Jul 30, 2026
d4d793f
Stop the scenarios' assertions passing without looking
epompeii Jul 30, 2026
67ad1de
Never report a measurement read that did not happen
epompeii Jul 30, 2026
402628e
Keep a chroot for its own cgroup, not for any stale jail
epompeii Jul 30, 2026
b3df643
Extend the table to what a run measures
epompeii Jul 30, 2026
1b46586
Announce the network namespace lock's wait
epompeii Jul 30, 2026
a02a1c2
Keep the API harness out of the real state directory
epompeii Jul 30, 2026
f599006
Put the absolute state directory rule on the type
epompeii Jul 30, 2026
4f0501b
Prove the state directory is ours by its tree, not by a name
epompeii Jul 30, 2026
201df93
Stop a failed stat from authorizing destruction
epompeii Jul 30, 2026
7eeccb2
Catch a jailed process that exits during the last sleep
epompeii Jul 30, 2026
f2aec94
Report a malformed HTTP response as malformed
epompeii Jul 30, 2026
47eef34
Warn about the jail user once per runner, not once per job
epompeii Jul 30, 2026
dfc253c
Say in the table that a read may gate an action
epompeii Jul 30, 2026
c6807fb
Search for one binary in one place
epompeii Jul 30, 2026
042ef29
Widen the syscall arguments explicitly
epompeii Jul 30, 2026
644b252
Say what the state directory actually holds
epompeii Jul 30, 2026
a378095
Write down why the metrics stat may stay
epompeii Jul 30, 2026
ea75511
Record the jail user warning when it is given
epompeii Jul 30, 2026
b3e1d7d
Fix a typo in the stale cgroup reasoning
epompeii Jul 30, 2026
f379837
Look once more before calling a VMM still running
epompeii Jul 30, 2026
1dbe0f5
Say why the grace period's fall-through is not the same bug
epompeii Jul 30, 2026
9ba83d5
Match the reap's outcomes exhaustively
epompeii Jul 30, 2026
82e2273
Document the invocation the scenarios actually accept
epompeii Jul 30, 2026
c6e92e2
Test that host tuning applies and unwinds
epompeii Jul 31, 2026
6d545bd
Document the tuning scenario
epompeii Jul 31, 2026
8350d9b
Remove the cgroup the tuning partition leaves behind
epompeii Jul 31, 2026
5303562
Have the tuning scenario diagnose its own partition failure
epompeii Jul 31, 2026
cc94a36
Reap what the state directory wipe would strand
epompeii Jul 31, 2026
fcd4c04
Refuse a state directory tree that is really a link
epompeii Aug 4, 2026
b19dcd3
Take back a state directory tree that is only half built
epompeii Aug 4, 2026
8521cac
Say what a failed sweep reclaimed before it failed
epompeii Aug 4, 2026
dbc6f5b
Say what makes a populated state directory ours
epompeii Aug 4, 2026
b738cf3
Say what a pidfd actually pins
epompeii Aug 4, 2026
7fbc05d
Wait on the VMM the reap pinned, not on its number
epompeii Aug 4, 2026
090709f
Wait out only the cgroup removal that waiting can fix
epompeii Aug 4, 2026
fe94488
Keep why enabling cpuset failed, so an absence is one
epompeii Aug 4, 2026
d33c748
Find the jailer that was orphaned before it chrooted
epompeii Aug 4, 2026
4210ccb
Name the flag the chroot teardown actually reads
epompeii Aug 4, 2026
9705bdc
Cover the rest of a chroot's creation with its own teardown
epompeii Aug 4, 2026
1e35821
Mint a local run's id instead of recovering a chroot it has none of
epompeii Aug 4, 2026
b5d7987
Reserve the port suffix on every socket path that can take one
epompeii Aug 4, 2026
3d5388a
Refuse an identity the runner could not have minted
epompeii Aug 4, 2026
14d21a0
Give the chroot's own creation a row in the table
epompeii Aug 4, 2026
8911a31
Hand the jailer none of the runner's environment
epompeii Aug 4, 2026
3aa6f72
Name the step that ran before the exec that failed
epompeii Aug 4, 2026
c85d284
Decide what an unpollable child means instead of falling through it
epompeii Aug 4, 2026
82bfb5c
Stop unlinking through the one view that can go stale
epompeii Aug 4, 2026
5366361
Degrade on the absence the host declared, not on the read that failed
epompeii Aug 4, 2026
60e48c2
Name the socket an API call could not reach after readiness
epompeii Aug 4, 2026
c13f3ff
Point the public docs at nothing they cannot reach
epompeii Aug 4, 2026
1fff3cd
Key the cached binaries to the release they came out of
epompeii Aug 4, 2026
c8f2289
Say that the staged binary's mode is set, not preserved
epompeii Aug 4, 2026
9db22a6
Keep saying why the runner is waiting for the jail lock
epompeii Aug 4, 2026
756a7b7
Answer a jail user of 0 with why root is no jail
epompeii Aug 4, 2026
8e2c407
Look for the binaries where cargo put them, not where the harness stands
epompeii Aug 4, 2026
ed08e2a
Hand back every tree the elevated run left root-owned
epompeii Aug 4, 2026
34f6f0f
Ask for a jail uid by name, and hold the VMM to that one
epompeii Aug 4, 2026
77b9c0e
Watch the namespace the VMM joined, not just the network it lacks
epompeii Aug 4, 2026
3fd69cd
Take the stacked mounts back off the handle the setup wedged
epompeii Aug 4, 2026
a4f6e3f
Pin that a jail the runner cannot build fails the job
epompeii Aug 4, 2026
2a6e31b
Reap the cgroups a killed daemon leaves nobody able to find
epompeii Aug 4, 2026
7e56f58
Stop the elevated runner on every way out of the test
epompeii Aug 4, 2026
e47e109
Say plainly why the handle is removed and not left mounted
epompeii Aug 4, 2026
af3a189
Wait out a cgroup the kill has not been reaped for
epompeii Aug 4, 2026
536dc00
Claim only what a snapshot of the host can show
epompeii Aug 4, 2026
56d902a
Match the failure-policy table to the pidfd reap that replaced the st…
epompeii Aug 4, 2026
ee635cb
Read the state lock name from the module that writes it
epompeii Aug 4, 2026
ecb18cb
Point the remaining public docs at nothing private
epompeii Aug 4, 2026
1b1bda9
Say why the chroot tightens by path where the state guard will not
epompeii Aug 4, 2026
ed84b37
Follow a state directory link only root could have aimed
epompeii Aug 4, 2026
da193f5
Hold the state tree as root, and read its listing before removing fro…
epompeii Aug 5, 2026
8163ecd
Retry the poll a signal interrupted
epompeii Aug 5, 2026
d36c0a2
Carry the error the vsock collection failed with
epompeii Aug 5, 2026
637ba40
Refuse a cpuset the runner could not parse
epompeii Aug 5, 2026
b8da28f
Document what one state directory holds and what it may be
epompeii Aug 5, 2026
b690cb6
Take the jailer into the guard the moment it exists
epompeii Aug 5, 2026
405ae3f
Wake the announcer on the way out of a panic too
epompeii Aug 5, 2026
80c6bc6
Judge the state directory link by an injected showing
epompeii Aug 5, 2026
1a54b24
Name the entries the archive actually lacked
epompeii Aug 5, 2026
8655ccf
Pin the config round trip to every field it skips
epompeii Aug 5, 2026
a265c1e
Name the binary whose mode could not be set
epompeii Aug 5, 2026
8453cc0
Say that a slow sweep is reclaiming rather than wedged
epompeii Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,20 @@ jobs:
run: |
echo '{"features": {"containerd-snapshotter": true}}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
- name: Build scenario binaries
run: cargo test-runner scenarios --build-only
- name: Run scenarios
run: cargo test-runner scenarios
# The scenarios run as root. The sandbox is built by dropping
# privilege rather than by starting without it: the jailer creates the
# chroot's device nodes with mknod, chowns the tree to the jail user,
# pivot_roots, and joins a network namespace. The udev rule above makes
# /dev/kvm usable by an unprivileged process, which is necessary but
# not sufficient.
#
# Only this step is elevated. The build above stays as the CI user, so
# cargo's cache and target directory are not left root-owned, and
# BENCHER_RUNNER_BIN keeps cargo out of the elevated step entirely.
run: sudo BENCHER_RUNNER_BIN=./target/debug/runner ./target/debug/test_runner scenarios

build_runner:
name: Build Runner (${{ matrix.build }})
Expand Down
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ Defined in `.cargo/config.toml`:
- `cargo test-api seed` needs the API server already running (`cargo run` in `services/api`) with a fresh database (`services/api/data` holds only a tracked `.gitignore`; delete `services/api/data/bencher.db`, not the whole directory)
- `cargo test-api seed` also needs the `bencher` CLI binary already built (`cargo build --bin bencher`); it shells out via `assert_cmd`, which panics with `` `CARGO_BIN_EXE_bencher` is unset `` if the binary is missing
- Pass `--no-git` when running the seed test in this repo: there is no colocated `.git`, so `bencher run` cannot derive a git context and the on-the-fly project naming assertions (`bencher` vs `Project`) will fail without it
- `cargo test-runner` - Runner integration tests (requires Linux + KVM)
- `cargo test-runner` - Runner integration tests (requires Linux + KVM + root)
- `cargo test-runner scenarios` always fails unelevated: the sandbox is built by dropping privilege, so the scenarios refuse to start without it. Build unprivileged, then run elevated, which also keeps `cargo` from leaving root-owned artifacts in `target`:
- `cargo test-runner scenarios --build-only`
- `sudo BENCHER_RUNNER_BIN=./target/debug/runner ./target/debug/test_runner scenarios`

## Git Flow

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion plus/bencher_runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ libc = { workspace = true }

# Linux-only dependencies
[target.'cfg(target_os = "linux")'.dependencies]
nix = { workspace = true, features = ["feature", "poll", "sched", "signal"] }
nix = { workspace = true, features = [
"feature",
"mount",
"poll",
"sched",
"signal",
] }

[build-dependencies]
flate2 = { workspace = true }
Expand Down
Loading
Loading