# DF-4453 — RVDA VBT mapping: pmap_mapbios() of firmware-supplied 64-bit address / 32-bit length with no validation (i915 OpRegion)

File: `sys/dev/drm/i915/intel_opregion.c` (pass 2)

## Root cause

`intel_opregion_setup()` maps the raw VBT pointer taken verbatim from the
firmware-shared ASLE mailbox:

```c
if (opregion->header->opregion_ver >= 2 && opregion->asle &&
    opregion->asle->rvda && opregion->asle->rvds) {
        opregion->rvda = pmap_mapbios(opregion->asle->rvda,      /* u64 phys addr :126 */
                                      opregion->asle->rvds);     /* u32 size     :127 */
        vbt = opregion->rvda;
        vbt_size = opregion->asle->rvds;
        if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
```
(`sys/dev/drm/i915/intel_opregion.c:1029-1043`)

* No check that `rvda`/`rvds` describe sane memory, no `rvda+rvds` overflow
  check, no upper bound on `rvds` (up to 4 GiB-1). DragonFly's
  `pmap_mapbios()` (`sys/platform/pc64/x86_64/pmap.c:6180`) maps **any**
  physical address with **any** length into KVA, write-back cached, and only
  fails by `panic("pmap_mapdev: Couldn't alloc kernel virtual memory")`
  (`pmap.c:6208`) — i.e. a large enough `rvds` request that exhausts the
  kernel_map KVA arena becomes a kernel *panic*, not an error return.
* The OpRegion contents (rvda/rvds) are SMM/firmware-writable shared memory.
* The mapping is re-established on every resume
  (`intel_opregion_setup()` called from `i915_drm_resume()`,
  `sys/dev/drm/i915/i915_drv.c:2124`) while `iounmap()` never releases
  `pmap_mapbios` KVA (the DF-1629 mechanism), so each suspend/resume cycle
  leaks up to `rvds` bytes of KVA + page-table entries: an unbounded
  *amplification* of DF-1629 by firmware-chosen size.
* Downstream is safe: a failed map (`rvda == NULL`) is rejected by
  `intel_bios_is_valid_vbt()`'s NULL check (`sys/dev/drm/i915/intel_bios.c:1655`),
  and the VBT block walks live in `intel_bios.c`, not in this file.

## Impact

Firmware-trust boundary issue (malicious/compromised VBIOS-SMM or a re-flashed
OpRegion): kernel KVA/PTE exhaustion (system-wide resource starvation, KVA
arena fragmentation), and in the `pmap_mapdev` OOM case a direct kernel panic
at boot. Not reachable from an unprivileged local user; no guest runtime test
possible (the audit QEMU guest has no Intel GPU — `i915` never attaches).

## Fix direction (see fix.diff)

Validate before mapping:
```c
if (opregion->header->opregion_ver >= 2 && opregion->asle &&
    opregion->asle->rvds >= sizeof(struct vbt_header) &&
    opregion->asle->rvds <= VBT_MAP_MAX &&              /* e.g. 4 MiB */
    opregion->asle->rvda &&
    opregion->asle->rvda + opregion->asle->rvds > opregion->asle->rvda) {
```
and bail to the mailbox-#4 VBT on validation failure (upstream Linux took the
same approach of bounding the rvda mapping, commit 6b4e4ba2cc02 family).
