# DF-5454 — PCIe MMIO config backend: missing reg+width bound → OOB access past pcie_base devmap

File under audit (pass 2): `sys/bus/pci/x86_64/pci_bus.c`
Sink: `sys/bus/pci/x86_64/pci_cfgreg.c` (`pciereg_cfgread`/`pciereg_cfgwrite`)

## What

The legacy host-PCI bridge config bridges `legacy_pcib_read_config` /
`legacy_pcib_write_config` (pci_bus.c:61-75) forward caller-supplied
`(bus, slot, func, reg, bytes)` to `pci_cfgregread`/`pci_cfgregwrite` with no
validation. When MMIO config space is active (`CFGMECH_PCIE` — Intel
7520/7320/915/925/915GM chipsets, pci_cfgreg.c:104-124, or any ACPI MCFG
table, sys/dev/acpica/acpi.c:1669), the request lands in
`pciereg_cfgread`/`pciereg_cfgwrite` (pci_cfgreg.c:315-365), which bound-check
only `reg > PCIE_REGMAX` (4095). They never check `reg + bytes <= 4096` and
never check alignment — both of which the port-I/O backend `pci_cfgenable`
(pci_cfgreg.c:187-193) enforces.

The MMCFG window is `pmap_mapdev_uncacheable(base, (maxbus+1) << 20)`
(pci_cfgreg.c:278-279) — with maxbus=255 a 256MB kernel_map allocation. The
highest mapped byte is (bus=255, slot=31, func=7, reg=0xfff). A 2-byte access
at reg=0xfff or 4-byte access at reg=0xffd/0xffe reads/writes 1-3 bytes past
the end of that kernel virtual allocation → kernel page fault (panic) or
silent corruption of the adjacent kernel mapping.

## Reachability / threat model

* `/dev/pci` PCIOCREAD/PCIOCWRITE (pci_user.c:602-673) checks
  `pi_width in {1,2,4}`, `pi_reg >= 0`, alignment — but sets **no upper bound
  on `pi_reg`** — then calls `PCIB_READ_CONFIG`/`PCIB_WRITE_CONFIG` → these
  bridges. Opening `/dev/pci` requires `SYSCAP_RESTRICTEDROOT`
  (pci_user.c:82) → **root-only**.
* Kernel-internal callers keep reg <= 0xff (capability walk clamps/aligns via
  `pci_fixup_nextptr`, pci.c:602-630). No in-tree caller passes reg>0xff
  except the ioctl.
* Requires CFGMECH_PCIE — dormant on QEMU i440FX (no MCFG; host bridge
  8086:1237 not in the chipset list), **active on most modern MCFG-bearing
  x86_64 hardware and on the listed Intel chipsets**.

Net: privileged-user-triggerable kernel OOB read/write (1-3 bytes) past a
kernel_map devmap allocation → reliable panic (DoS), potential corruption of
the adjacent kernel mapping. Severity: Low (already-privileged attacker).

## Reproduce (this pack)

1. `build.sh` — compile the KLD inside the guest (needs /usr/src, cc, make).
2. `run.sh` — `kldload /root/df5454/df5454.ko` as root.

The KLD performs the exact legal `pcie_cfgregopen()` call the platform/ACPI
makes at boot (activating CFGMECH_PCIE — dormant on the i440FX guest), then:

* CONTROL: in-bounds read (255,31,7,0xffc,4) — succeeds, no fault.
* step2: OOB read (255,31,7,0xfff,2) — **Fatal trap 12, supervisor read,
  page not present**, fault VA exactly `pcie_base + 0x10000000`.
* step3/4: OOB write / 3-bytes-past read (only reached if step2 survives).

Expected (vulnerable kernel): panic at step2 — see `panic.txt`.
Expected (patched kernel, fix.diff): no panic; step2 returns 0xffffffff
(rejected), module load completes, guest stays up — see `run_patched.log`.

## Fix

`fix.diff` — carry the mech-1 backend's width/alignment/end bound into
`pciereg_cfgread`/`pciereg_cfgwrite`. Validated: baseline panics, patched
kernel rejects the access and boots/runs normally.
