# DF-2027 — VBIOS table parsers dereference attacker-controlled offsets without bounds

## Verdict
**CONFIRMED (source-trace); NOT REPRODUCED AT RUNTIME — HW-GATED.**
Status: `inconclusive`, reproduced=0. The defect is real (the offset is read from the
VBIOS image and never bounds-checked), but it cannot be exercised on this guest: there is
no AMD GPU (`amdgpu.ko` is not loaded; the guest's only display device is plain VGA, not
AMD), so none of the `amdgpu_atomfirmware_*` parsers run.

## Mechanism (confirmed)

`amdgpu_atom_parse_data_header()` is the single choke point that hands every VBIOS table
parser its table pointer:
- `sys/dev/drm/amd/amdgpu/atom.c:1384-1403`
  - `:1388-1389` — `int offset = index*2+4; int idx = CU16(ctx->data_table + offset);`
    `idx` is a 16-bit value read **directly from the VBIOS image** (`CU16` →
    `get_u16(ctx->bios, ptr)`, `sys/dev/drm/amd/include/atom-bits.h:39`).
  - `:1401` — `*data_start = idx;`  returns `idx` with **NO validation** that
    `idx + sizeof(table)` lies within the BIOS buffer (`ctx->bios`, a `kmalloc`'d image of
    `adev->bios_size` bytes — `sys/dev/drm/amd/amdgpu/amdgpu_bios.c:111` etc.).

Every parser in `sys/dev/drm/amd/amdgpu/amdgpu_atomfirmware.c` then does
`(ctx->bios + data_offset)` cast to a struct pointer and reads fields — e.g.
`:42-43` `amdgpu_atomfirmware_get_gpu_clock_info`, `:62`, `:80`
(`vram_usagebyfirmware`), `:141`, `:217`, `:264`, `:287`, `:310`, `:346`. With a crafted
VBIOS (attacker controls the image via VFIO/PCI romfile passthrough, a compromised ACPI
VFCT table, or a reflashed ROM — all noted in the parent finding), `data_offset` can point
past `bios + bios_size`, so each struct-field read is an **OOB heap read** of the
kmalloc'd VBIOS buffer into adjacent slab objects. Class: CWE-125.

The README's crafted-VBIOS example (1024-byte image, `data_offset = 980` for firmwareinfo)
is consistent with this: `firmware_info` at `bios+980` extends ~68 bytes, so
`reserved2[6]` at offset 44-67 reads `bios+1024..bios+1047`, 23 bytes past the allocation.

## Why it is not reproduced on this guest (HW-gate)
- `pciconf -lv` shows no AMD display device (only a generic VGA); `kldstat -v` shows no
  `amdgpu` module.
- The parsers run only during AMD GPU init (`amdgpu_device_init` → `amdgpu_atombios_*`),
  which never executes without AMD hardware. The crafted-VBIOS preconditions (VFIO
  passthrough of an evil ROM / compromised VFCT) require a host/firmware an unprivileged
  guest user cannot arrange on this audit guest.
- No userspace harness can reach these parsers without an AMD GPU.

Threat model: an attacker who controls the VBIOS image presented to the driver (compromised
VM host, compromised firmware, or physical reflash). This is a latent/remote-image class
bug, not a local-syscall privesc. No escalation chain was developed (it is a heap OOB read,
not a write primitive, and is unreachable here).

## PoC changes
None (source-only verification).

## Fix (`fix.diff`)
Root-cause fix at the choke point, touching three files:
1. `sys/dev/drm/amd/amdgpu/atom.h` — add `uint32_t bios_size;` to `struct atom_context`.
2. `sys/dev/drm/amd/amdgpu/atom.c` — initialize `ctx->bios_size = 0` in
   `amdgpu_atom_parse()`, and in `amdgpu_atom_parse_data_header()` validate, before
   returning `data_start`, that `[idx, idx + tbl_size)` (where `tbl_size = CU16(idx)` is the
   table's own declared size) lies within `ctx->bios_size`; return `false` otherwise.
   `bios_size == 0` (legacy/unknown) skips the check for back-compat.
3. `sys/dev/drm/amd/amdgpu/amdgpu_atombios.c` — set
   `atom_context->bios_size = adev->bios_size` right after `amdgpu_atom_parse()`.

This single choke-point fix protects all ~10 `amdgpu_atomfirmware_*` parsers (and every
other `amdgpu_atom_parse_data_header` consumer) because none can receive an out-of-range
`data_start`. Supersedes the finding proposal's per-parser approach with a single,
maintainable bounds check at the offset source.

## Fix validation (Phase 8)
Combined kernel build with all four fixes: **rc=0, 0 warnings, 0 errors under -Werror**;
`atom.c`, `amdgpu_atomfirmware.c`, `amdgpu_atombios.c` all recompiled and `amdgpu.ko`
(101 MB) relinked (see `fix_build.log`). HW-gated ⇒ `fix_status = not_testable` (diff
applies + compiles cleanly under -Werror + traced to close the path; no AMD GPU to run a
runtime demonstration).
