What rust-vmm Is
rust-vmm is a community project, not a product. It ships a set of small Rust
crates — each in its own GitHub repository under the rust-vmm organization —
that several virtual machine monitors build on. There is no rust-vmm binary,
no VMM you can boot, no release that bundles everything. There is kvm-ioctls,
there is vm-memory, there is linux-loader, and a couple dozen siblings, each
versioned and published to crates.io independently. Firecracker consumes a
subset; Cloud Hypervisor consumes a larger subset; both pull from the same
audited code. This chapter is the why and the how of that arrangement, and
the one fact you most need as a contributor: a Firecracker change sometimes
belongs upstream, in a rust-vmm crate, not in the Firecracker tree.
After this chapter you can: explain the philosophy that justifies the project;
describe its per-repo + gatekeeper governance and the community repo; explain
what rust-vmm-ci enforces; outline how a new crate gets added; and decide, for
a given change, whether it lands in firecracker or upstream.
Note: This is the contributor-mindset companion to the crate chapters that follow. The crate chapters teach you the code; this chapter teaches you the project — and the boundary between "fix it here" and "fix it upstream" is a judgment call maintainers will expect you to make correctly.
The philosophy: write the dangerous code once
A VMM is a privileged host process whose whole job is to safely run untrusted guest code. The lowest layers of that job are also the most dangerous:
- FFI to the KVM
uapi— get a struct layout or anioctlnumber wrong and you have undefined behavior in code that talks to the kernel. - Guest-memory access — every read and write must be bounds-checked against attacker-influenced addresses, or you have an out-of-bounds host access.
- Virtqueue parsing — the descriptor table, available ring, and used ring are all in guest memory, fully attacker-controlled; a naive parser is an escape primitive.
- Raw
ioctl/mmap/eventfdplumbing — theunsafeglue every VMM needs.
Before rust-vmm, every Rust VMM re-implemented all of this. Firecracker had its
own. crosvm had its own. Cloud Hypervisor (then "cloud-hypervisor") had its own.
Three subtly different copies of the most security-critical code in the stack,
each with its own bugs, each fuzzed (or not) independently. The rust-vmm thesis
is blunt: don't re-implement low-level VMM code — share it, and audit it
once. One vm-memory with one set of bounds checks, fuzzed continuously, used
by everyone, is safer than three hand-rolled copies. The same argument that
makes a minimal device model good for Firecracker's security makes a shared,
audited foundation good for the whole ecosystem.
flowchart LR
subgraph before["Before rust-vmm"]
A1["Firecracker:\nown kvm/mem/loader"]
A2["crosvm:\nown kvm/mem/loader"]
A3["Cloud Hypervisor:\nown kvm/mem/loader"]
end
subgraph after["With rust-vmm"]
B1["Firecracker"] --> S["one audited\nkvm-ioctls / vm-memory /\nlinux-loader / ..."]
B2["Cloud Hypervisor"] --> S
B3["others"] --> S
end
This is not free. Sharing a crate means coordinating across companies with different priorities; it means a change you want has to be acceptable to Cloud Hypervisor too; it means slower iteration than editing your own tree. Firecracker deliberately keeps some things in-tree because of that cost — most visibly its virtio device implementations (see virtio-queue.md), where it wants tight control over the exact device behavior and attack surface. The in-tree-vs-upstream line is a real engineering trade-off, decided case by case.
Governance: per-repo maintainers, gatekeepers, the community repo
rust-vmm is decentralized by design. There is no single steering committee that owns all the code. The structure:
| Layer | What it is | Where to find it |
|---|---|---|
| Per-repo maintainers | Each crate repo has its own listed maintainers who review and merge that crate's PRs. | each repo's CODEOWNERS / README / MAINTAINERS |
| Gatekeepers | A small org-wide group with admin rights, handling cross-cutting decisions, new repos, releases, security. | the rust-vmm/community repo |
The community repo | The org's "constitution": meeting notes, the new-crate proposal process, membership rules, the code of conduct, the CI submodule. | github.com/rust-vmm/community |
# Read the governance directly — it is short and authoritative:
# github.com/rust-vmm/community → README, MAINTAINERS, meeting notes
# For any single crate, the maintainers are in its own repo, e.g.:
# github.com/rust-vmm/kvm-ioctls → CODEOWNERS / README
Contribution is by GitHub PR, no CLA, with sign-off discipline and the usual
expectation that each commit is buildable, tested, and clippy-clean. Because each
crate is independent, the people who review your vm-superio change are not
necessarily the people who review your kvm-ioctls change — and several of them
are also Firecracker maintainers wearing the other hat. That overlap is why
"upstream first" is a credible path: the same AWS engineers maintain parts of
both.
Tip: Firecracker's own
MAINTAINERS.mdand the rust-vmm crateCODEOWNERSoverlap. When you propose an upstream change, you are often talking to people who already know Firecracker's needs — frame the change in terms of all consumers (Cloud Hypervisor included), not just Firecracker.
rust-vmm-ci: one bar for every crate
The thing that keeps a federation of independent crates at a uniform quality is
rust-vmm-ci — a shared CI configuration distributed as a git submodule
that each crate repo pulls into itself. Instead of every crate inventing its own
pipeline, they all run the same checks:
| Check | What it enforces |
|---|---|
cargo build (multi-target) | builds on x86_64 and aarch64, stable + MSRV |
cargo test | unit + integration tests, sometimes under multiple feature sets |
cargo clippy -- -D warnings | lints are errors, exactly like Firecracker |
cargo fmt --check | formatting is enforced, not suggested |
| coverage | a per-crate coverage floor that a PR may not lower |
| fuzzing (where applicable) | continuous fuzzing of the parsers (e.g. virtio-queue) |
| commit/style checks | sign-off, commit message hygiene |
# In any rust-vmm crate checkout you'll see the submodule:
git submodule status # lists rust-vmm-ci
ls rust-vmm-ci/ # the shared pipeline definitions
If you have internalized Firecracker's tools/devtool checkstyle / checkbuild --all / warnings-as-errors clippy gate (see
Lab 2.2), rust-vmm-ci will feel familiar
— it is the same discipline, applied across the ecosystem. A change that passes
Firecracker's bar is most of the way to passing rust-vmm-ci.
How a crate gets added
New crates don't appear by accident. The community repo documents the process,
which in practice looks like:
- Propose a new crate in the
communityrepo (an issue / meeting agenda item): what problem it solves, why it belongs shared, who will maintain it. - Discuss in the regular community meeting — is the scope right, does it overlap an existing crate, is there more than one willing consumer?
- Bootstrap the repo with
rust-vmm-ci, an initial maintainer set, and the standard license (Apache-2.0, often dual with BSD/MIT). - Publish to crates.io once it stabilizes.
Three of the crates you will read about took a shortcut through this process:
they were donated from Firecracker. seccompiler, event-manager, and
vm-superio were extracted out of the Firecracker tree, generalized so they were
not Firecracker-specific, and contributed upstream so the whole ecosystem could
share them. That is the highest-leverage move available to a Firecracker
contributor — not just fixing the foundation, but enlarging it.
The monorepo consolidation
For most of its history rust-vmm was strictly one crate per repository — dozens of small repos. That has costs: cross-crate changes need coordinated PRs across repos, dependency bumps ripple slowly, and the submodule-per-repo CI is heavy. The project has been consolidating related crates into shared repositories (for example, grouping the virtio crates together) to make cross-cutting work tractable, while still publishing each crate independently to crates.io. The direction — fewer repos, same independent crates — is what to remember; the exact current grouping is something to check on the org page, because it moves.
Note: Because repo boundaries are shifting, never assume "crate X lives in repo X." Find the source from your dependency, not from memory:
# From the FC checkout, jump straight to a dependency's source: cargo doc -p vm-superio --no-deps --open # docs for the pinned version # Or find where cargo unpacked it: find ~/.cargo/registry/src -maxdepth 1 -type d -name 'vm-superio-*'
Why this matters to a Firecracker contributor
Here is the practical payoff, and the reason this chapter exists at all. When you triage a Firecracker issue or design a fix, you must answer a routing question that a less experienced contributor gets wrong: whose code is this?
| Symptom / change | Likely home | Why |
|---|---|---|
| Serial console drops a byte under load | vm-superio (upstream) or FC's use of it | the UART model is the shared Serial |
KVM_RUN exit not handled / a new VcpuExit variant needed | kvm-ioctls (upstream) | the exit enum is defined there |
| Guest-memory bounds check too strict/loose | vm-memory (upstream) | the GuestMemory impl owns bounds |
Kernel fails to load a valid vmlinux | linux-loader (upstream) | the ELF parser is the shared loader |
| A seccomp JSON operator behaves wrong | seccompiler (upstream-origin) | the compiler is shared |
| FC's virtio-block request handling | firecracker (in-tree) | FC keeps its own virtio devices |
| FC's API server validation | firecracker (in-tree) | wholly FC-specific |
| FC's snapshot format | firecracker (in-tree) | FC-specific persistence |
Get this wrong and your PR goes to the wrong repo, the wrong reviewers, and the wrong test suite. Get it right and you become the kind of contributor who fixes the foundation — a fix that ships to Cloud Hypervisor too, then flows back into Firecracker on the next version bump. The mechanics of doing that — forking a rust-vmm repo, the PR, the version-bump-then-consume cycle — are Lab R4.
There is a second-order skill here too: dependency bumps. Periodically
Firecracker raises its pinned rust-vmm versions. Someone has to do that PR — bump
the Cargo.toml, regenerate Cargo.lock, fix whatever API breaks, re-run the
pytest suite. It is recurring, high-visibility, trust-building work, exactly like
"upgrade the bundled Lucene" is in OpenSearch. Find the history:
# Past rust-vmm version-bump PRs are a model for your own:
gh search prs --repo firecracker-microvm/firecracker "Update kvm-ioctls OR Update vm-memory OR bump rust-vmm" --limit 20
git log --oneline -- Cargo.lock | head -20
Validation: prove you understand this
- State the rust-vmm thesis in one sentence, and connect it to the same security argument that justifies Firecracker's minimal device model.
- Describe the governance: per-repo maintainers, gatekeepers, and the role of
the
communityrepo. Where do you read the actual rules? - What does
rust-vmm-cienforce, and how is it distributed to each crate? Name three checks it shares with Firecracker'sdevtool. - Name the three crates Firecracker donated upstream, and explain why donating a crate is higher-leverage than fixing one.
- Given a bug where the serial console drops bytes, and another where the API server mis-validates a drive, say which repo each fix belongs in and why.
- Explain what a "rust-vmm version bump" PR in Firecracker involves and why it is trust-building work.
Next: kvm-ioctls and kvm-bindings — the safe
RAII wrappers and the raw uapi FFI that put Firecracker in touch with KVM.