# DF-1210 — VERDICT

**Finding:** OOB read in the AHCI DHRS error path: a device-controlled CCS
slot index is dereferenced before any bounds check
(`sys/dev/disk/ahci/ahci.c`).
**Status:** NOT TESTABLE on this audit guest. **Confidence (bug is real):** certain.
**Impact ceiling:** kernel OOB array index + garbage-pointer deref → panic /
controlled memory access; **device-controlled** (malicious AHCI controller).
**Fix:** authored in `fix.diff`, applied clean, compile-validated into the
GENERIC kernel (`fix_build.log`).

## Mechanism (confirmed line-by-line in `sys/`)

1. `ahci_port_intr()` (`ahci.c`) handles the DHRS (D2H Register FIS) interrupt.
2. `ahci.c:2643` — `int err_slot;` declared inside the TFES block;
   `process_error:` label is at `ahci.c:2651`.
3. DHRS branch `ahci.c:2809` (`else if (is & AHCI_PREG_IS_DHRS)`):
   - `ahci.c:2832-2833` reads `tfd` (PxCMD_TFD) and `cmd` (PxCMD).
   - `ahci.c:2843-2844` — on `(tfd & ERR) && !(cmd & ST)`:
   - `ahci.c:2845-2846` — `err_slot = AHCI_PREG_CMD_CCS(ahci_pread(ap, AHCI_PREG_CMD));`
     `AHCI_PREG_CMD_CCS(_r) = ((_r) >> 8) & 0x1f` (`ahci.h:183`) → **5-bit, 0-31**.
   - `ahci.c:2847` — `ccb = &ap->ap_ccbs[err_slot];` **NO bounds check.**
     `ap_ccbs[]` is allocated for `sc->sc_ncmds` slots (4-32, set from the
     controller's CAP.NCS).
   - `ahci.c:2850` — `kprintf("... cmd=%02x", ..., ccb->ccb_xa.fis->command)` —
     derefs the OOB `ccb` then a garbage `fis` pointer.
   - `ahci.c:2851` — `goto process_error;` carries the (still unchecked) slot.
4. Compare the TFES path, which **does** validate first: `ahci.c:2724` —
   `else if (err_slot < 0 || err_slot >= ap->ap_sc->sc_ncmds) { ... err_slot=-1; }`.
   The DHRS path is the asymmetric, missing-check sibling.

So a CCS value in `[sc_ncmds .. 31]` indexes past `ap_ccbs[]`. The damage
(read of OOB `ccb`, then `fis->command` deref) occurs at `ahci.c:2847-2850`
before any later check can run.

## Why it is NOT TESTABLE on this guest

- `pciconf -l` lists no AHCI/SATA controller; the guest root disk is
  virtio-blk (`/dev/vbd0`), the only storage besides a SCSI DVD-ROM. `ahci(4)`
  is in GENERIC but **did not attach** to any device, so `ahci_port_intr()` is
  dead code at runtime here.
- The attacker-controlled input (`err_slot` via CCS) is a hardware register
  read from the AHCI controller. On a benign controller CCS is always a slot
  the driver actually issued (< sc_ncmds). There is **no userspace syscall**
  that can make a benign QEMU AHCI model return CCS >= sc_ncmds, so even if an
  AHCI device were added it would not fire from an unprivileged user.

Valid "device-controlled, not reachable from an unprivileged user on this
guest" case. The bug is genuine (asymmetric missing bounds check confirmed
against the sibling TFES path); threat model = malicious/buggy AHCI
controller (peripheral / malicious VM device-model).

## Exploit chain
None developed: the primitive is reachable only via a malicious AHCI
controller's CCS register, not via any unprivileged local syscall. On this
guest there is additionally no AHCI device at all. Documented impact ceiling:
panic / OOB memory access driven by the controller.

## Fix
`fix.diff` adds the same bounds check the TFES path uses, immediately after
the CCS read and before `ap_ccbs[err_slot]`:
```c
err_slot = AHCI_PREG_CMD_CCS(ahci_pread(ap, AHCI_PREG_CMD));
if (err_slot < 0 || err_slot >= ap->ap_sc->sc_ncmds) {
	kprintf("%s: DHRS bad error slot %d\n", PORTNAME(ap), err_slot);
	err_slot = -1;
	goto process_error;
}
ccb = &ap->ap_ccbs[err_slot];
```
A bad slot is routed through `process_error` (which re-reads CCS and falls
into the TFES `err_slot < 0` → `failall`/reset handling). Minimal, targeted,
symmetric with the existing TFES guard.

## Build / run on this guest
`./build.sh && ./run.sh` is a reachability probe. On this guest it reports
"no ahci controller attached → DHRS path unreachable"; the bug is confirmed
by the source trace above and the fix is compile-validated into GENERIC.
