Overview
- What: a Linux container runtime in Rust where every syscall, netlink message and the JSON and TOML parsers are hand-written against the kernel ABI.
- Hardest problem: bringing a container up and tearing it down transactionally, with no leaked veth, cgroup or IP lease when any step fails.
- How it is validated: 19 named fault-injection points, each fired by an integration suite that checks resources return to baseline, plus 205 tests.
myrun creates real containers with separate PID, mount, UTS, IPC, network and cgroup namespaces, a pivoted root filesystem, cgroup v2 limits, a bridged network with NAT and port publishing, capability dropping, no_new_privs and a seccomp filter. Three cooperating processes (CLI, shim and init) run each container, with a rollback stack for everything created on the way up.
Architecture
Highlights
- Hand-written kernel ABI layer:
clone3withCLONE_INTO_CGROUP, pidfd,pivot_root(".", "."), capget/capset, BPF seccomp assembly, signalfd, and rtnetlink for veth, bridge, addresses and routes. - A ready/go/started handshake between parent and init over a socketpair removes the races between network setup and
pivot_root; a sealed memfd copy of the binary mitigates CVE-2019-5736. - 14 commands (
run,create,start,stop,kill,pause/unpause,rm,ls,inspect,stats,logs,wait,gc,info), TOML/JSON config files, named containers and id-prefix lookup. - Failure handling proven, not asserted: 19 named fault-injection points (
MYRUN_FAULT=after_veth_create), and an integration suite that fires every point and checks veth, cgroup and IP-lease counts return to baseline. - 155 unit + 9 CLI tests that run without privileges, plus 41 privileged tests; Rust 1.70+, and no
Cargo.lockto audit. - Documented limits (root only, no
exec, no OCI images, cgroup v2 only, iptables shelled out) and six docs includingbugs.md, which records every real bug found and its fix.
What I learned
Fault injection turned “cleanup works” from a belief into a measured property: I could fire each of the 19 points and count resources. The ready/go/started handshake came from chasing races between network setup and pivot_root. Keeping a bugs.md of every real bug made the design decisions easier to defend.
Limits
Root only, no exec, no OCI images, cgroup v2 only, and iptables is shelled out.