diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-21 03:29:12 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-21 03:29:12 -0400 |
| commit | 0b307461d22a7bfa85d4ec87b80a0e5205fc3cd6 (patch) | |
| tree | 1862e0c6a6b9492bc47a9739f11c5eedb5409ead /docs/05-operations/05-gpubreach-audit.md | |
| parent | 7a1f48057fe3bd96d26d9ae3f85263ffdd93d374 (diff) | |
| download | open-iov-0b307461d22a7bfa85d4ec87b80a0e5205fc3cd6.tar.gz open-iov-0b307461d22a7bfa85d4ec87b80a0e5205fc3cd6.zip | |
docs: GPUBreach-class audit and threat model for the host write paths
Audit of every host-side write whose target derives from guest data,
against the GPUBreach (IEEE S&P 2026) chain: GPU PTE corruption ->
arbitrary device read/write -> driver bugs -> CPU root.
Findings: the host is structurally off that path (guest GPU page tables
host-emulated, physical GPU PTEs host-owned, every write aperture-bounded
by vfio_dma_rw to guest RAM or the vidmem shadow, no guest DMA to host
buffers), and the remaining wrong-but-valid write class is bounded by the
per-page resolution + refusal guards (FILL-TRUNC, FILL-PT-REFUSED,
LOWFILL-REFUSED, GRFILL-DROP, stalled-VA demand, sema_copy_dst_pin_guard,
DST-DIVERGE). Documents residual risks, what is not claimed (no isolation
or side-channel claim; physical Rowhammer is out of scope), and three
follow-ups.
Diffstat (limited to 'docs/05-operations/05-gpubreach-audit.md')
| -rw-r--r-- | docs/05-operations/05-gpubreach-audit.md | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/docs/05-operations/05-gpubreach-audit.md b/docs/05-operations/05-gpubreach-audit.md new file mode 100644 index 0000000..3c60385 --- /dev/null +++ b/docs/05-operations/05-gpubreach-audit.md @@ -0,0 +1,95 @@ +# GPUBreach-class audit and threat model (vGPU host module) + +Status: audit performed 2026-10-21 against the host module at `229bec2c` +(`vgsp.ko`, `kernel/`), with the write-path guards landed in the same window +(`7d4919dd`, `7a1f4805`). Scope: every host-side write whose target address +derives from guest-supplied data. Companion reading: +[`01-performance-correctness-security.md`](01-performance-correctness-security.md). + +## 1. What the GPUBreach threat is + +GPUBreach (IEEE S&P 2026, U. Toronto) is a GPU Rowhammer chain: the attacker +flips bits in the physical GPU's page tables (PTEs), which turns the GPU's +MMU into an arbitrary *device-memory* read/write primitive; the paper then +escalates to CPU root by exploiting memory-safety bugs in the *driver* code +that consumes those corrupted translations. It works with the IOMMU on, +because the corruption happens inside the GPU, after translation. + +The relevant question for this project is therefore not "can a guest read +device memory" (device memory is the guest's own resource here) but: + +1. can guest-influenced data reach a *host* write without validation, and +2. what bounds a write that lands on a *wrong* target. + +## 2. Structural mitigations (why the host is not on that path) + +* **Guest GPU page tables are host-emulated.** The guest's GMMU page tables + live in the emulated vidmem shadow (BAR1 backing) or in guest RAM; the + host resolves guest GPU VAs through its own walk of the guest's published + page directories (`SET_PAGE_DIRECTORY`) or through content-verified pins. + There is no physical GPU MMU walk of guest-authored tables. +* **The physical GPU's PTEs are host-owned.** Backend jobs are submitted by + the host module on host-authored PTE lines; the guest never supplies a + descriptor that the real hardware MMU consumes for host memory. +* **Every write is aperture-bounded.** The one write primitive, + `svc_write_ap()`, sends SYS writes through `vfio_dma_rw()` on the mdev's + own VFIO container - the IOMMU/vfio layer only maps the guest's RAM - and + FB writes are bounds-checked against the emulated shadow size. A + guest-influenced target can therefore only ever land inside the guest's + own RAM or the vidmem shadow; a wrong target is a correctness bug, not a + host-memory write. +* **No guest DMA to host buffers.** The guest's drivers talk to the + emulated device; they cannot address host kernel buffers. IOMMU is on + (vfio), and the mdev exposes only guest RAM plus the emulated windows. +* **Guest descriptors are not trusted by construction.** Every path that + turns a guest VA into a host PA goes through the resolution chain + (guest-verified injected pins -> write/read landing ledger -> published + page-directory walk -> targeted record scan), and the chain's outputs are + re-validated per page (see ยง3). + +## 3. Write-path inventory and validation state + +| Write path | Target derivation | Validation today | +|---|---|---| +| CE fill / memset (`svc_fill`) | guest VA or physical FB/GPA from the push | per-page destination resolution (pin -> ledger -> walk), page-boundary clamped; a page with no resolution truncates loudly and demands the VA through the pin channel (`FILL-TRUNC`, `stalled VA`); zero fills onto page-table-shaped guest pages are refused (`FILL-PT-REFUSED`); below-floor window fills that resolve outside vidmem are refused (`LOWFILL-REFUSED`) | +| CE copy (`svc_copy`) | dst/src VAs from the push | per-page resolution with pin-agreement (a fresh pin beats a stale ledger entry and repairs it); device-dst copies without a pin-resolved translation are held (`sema_copy_dst_pin_guard`) | +| GRCE inline writes (`LOAD_INLINE_DATA`) | destination VA from the push | once-only identity gate keyed by (push VA, push content hash, dst, bytes), session-scoped and 8192 slots wide | +| GR launch operand staging (`svc_gr_data_fill`) | argument pointers scanned from the QMD | per-page pin/ledger resolution; the resolution is stored in the ledger as the landing authority; dropped pages are named (`GRFILL-DROP`) and demanded | +| Launch copy-out (engine results back to the shadow/guest page) | the launch's own landing records | per-page destination resolution; every write is witnessed (`OUT-PAGE-WIT`/`OUT-PAGE-POST`); staged-identity rule (only the page staged into a slot may receive the slot's content) | +| Release/counter writes (semaphores, completion counters) | guest semaphore VAs from pushes | pool-range writes go through a pin/record-verified cache (`pool-pa`), re-validated against the current pin before the 4-byte write; exact-slot fallback for the client's tracker; forward-only apply | +| GPFIFO/USERD writes (put/get bookkeeping) | channel registration data | the channel's own USERD/instance blocks from the alloc params, aperture-tagged | +| Window/PTE installs (forward PDE install) | the launch's windows | installs are refused loudly when the backend rejects the PDE; the regular path leaves guest VAs in place (no host-side table mutation) | + +## 4. Residual risks and findings + +* **Wrong-but-valid writes remain possible** when every resolver agrees on a + stale page (e.g. a guest freed and reallocated a VA). The r391/r398/r401 + fixes removed the known instances (contiguous fill past the first page, + replayed inline writes, capture-window eviction), but the class is bounded, + not eliminated: the guards convert silent corruption into loud + truncation/refusal where a page is unresolved, and the ledger is + session-scoped and pin-repaired where a fresh pin exists. +* **The boot-corruption lottery** (a zero fill landing on guest page-table + pages) is structurally mitigated by the page-table-shape refusal and the + per-page clamping; no instance has been observed since r391. +* **Diagnostics stay on**: `DST-DIVERGE` (copy-dst ledger vs probe), + `FILL-TRUNC`, `GRFILL-DROP`, `NOWRITE-*` and the stalled-VA demand rows + exist so a future divergence is visible in the boot log rather than + silent. +* **What this audit does not claim**: no isolation or side-channel claim. + GPU Rowhammer itself is a *physical* fault-injection threat that this + software emulation cannot mitigate; the mitigation argument here is only + that the host write paths cannot be steered outside the guest's own + memory, and that wrong targets are bounded by IOMMU-mapped guest RAM or + the emulated shadow. + +## 5. Recommended follow-ups + +1. Keep the copy-destination ledger under the `DST-DIVERGE` witness and + promote it to a bounded hold only if a failing run names it. +2. Extend the pin-demand channel to client device VAs (today the in-guest + scanner resolves only its own push/table windows), so an unresolved + operand page becomes a wait on real data instead of a truncated fill. +3. Re-run this audit when the write-path guards change (any new + `svc_write_ap()` caller with a guest-derived target is in scope by + default). |
