# DF-4221 — pvscsi_process_completion dereferences a NULL ccb on duplicate/spurious device completion

File: `sys/dev/virtual/vmware/pvscsi/pvscsi.c` (pass 2; DF-1454/DF-1455 excluded, not re-reported)

## What

`pvscsi_process_completion()` (pvscsi.c:888-1035) resolves the completion
entry's hypervisor-fed `e->context` to an hcb and then dereferences
`hcb->ccb` **without any NULL check**:

```c
hcb = pvscsi_context_to_hcb(sc, e->context);   /* :899  (range = DF-1455) */
callout_stop(&hcb->callout);                   /* :901 */
ccb = hcb->ccb;                                /* :903 */
btstat = e->host_status;                       /* :905 */
sdstat = e->scsi_status;                       /* :906 */
ccb->csio.scsi_status = sdstat;                /* :908  <-- NULL write if ccb==NULL */
ccb->csio.resid = ccb->csio.dxfer_len - e->data_len;  /* :909 */
```

`hcb->ccb` is NULL for every hcb that is not in flight: it is set NULL by
`pvscsi_hcb_put()` (pvscsi.c:382) on completion and on every error path.
The driver's own timeout handler **does** guard this exact case
(`pvscsi_timeout`, pvscsi.c:850-853: `if (ccb == NULL) { /* Already completed */ return; }`),
but the completion path does not.

Trigger (device/hypervisor-fed, same trust boundary as DF-1454/DF-1455):
the completion ring is DMA shared with the virtual device; a malicious or
buggy VMware host can emit

* a **duplicate** completion for a context that was already completed
  (the hcb is back on the free list, `ccb == NULL`), or
* a **spurious** completion for a valid-but-never-issued context
  (hcb never left the free list, `ccb == NULL`).

Result: write of `sdstat` (device-controlled 16-bit expanded to u32) to the
fixed low address `offsetof(union ccb, csio.scsi_status)` (~0xB0) and
immediately further NULL-based writes/reads (:909, :911-918, :1018-1034) ⇒
kernel page fault ⇒ **panic** (NULL page is unmapped). This is distinct from
DF-1455 (out-of-range `context` ⇒ wild `hcbs + (context-1)` pointer): here
the context is in-range and the hcb is valid — only the missing `ccb == NULL`
check matters.

## Reachability

Requires a pvscsi controller (VMware hypervisor presenting 15ad:07c0) — the
attacker is the host/hypervisor side of the paravirtual device. The driver is
compiled into X86_64_GENERIC (`sys/config/X86_64_GENERIC:147`). Not
triggerable on the audit guest (QEMU exposes no pvscsi device — verified:
no 15ad PCI devices), hence source-level certainty + fix build validation
only.

## Reproduce / validation

No live trigger on this guest. `VERDICT.md` carries the line-by-line trace.
`fix.diff` (NULL-ccb guard mirroring `pvscsi_timeout`'s) applies cleanly to
the pristine guest kernel source and the pvscsi module rebuilds with the
guard compiled in (`build.log`; the guard's format string is present in the
resulting `pvscsi.ko`).

## Files

`VERDICT.md`, `fix.diff`, `patch_apply.log`, `build.log`,
`build_baseline.log` (unpatched build), `env.txt`, `manifest.json`,
`verdict.json`
