# DF-2300 — missing privilege check in FWOHCI_WRREG/RDREG/PHYREG ioctls

## What this is
Verification pack for finding DF-2300 (`sys/bus/firewire/fwohci.c:354-392`).
Medium / operator-group arbitrary OHCI register access. Claim:
`fwohci_ioctl()` (fwohci.c:333-398) services FWOHCI_WRREG / FWOHCI_RDREG /
FWOHCI_WRPHYREG / FWOHCI_RDPHYREG / DUMPDMA with **no privilege check of any
kind**; the /dev/fw* nodes are 0660 root:operator, so any operator-group
user can program the OHCI DMA engine registers (context command pointers,
interrupt masks, HCC link/reset control) and the PHY.

## Verdict (short)
REPRODUCED on the verbatim-interposition harness (kernel-compiled,
`fwohci.c` TU-included unmodified): an operator-group user (`opuser`,
gid operator) issued, through the REAL dispatch chain
`/dev/fw0.0 -> fw_ioctl (fwdev.c:411) -> default: sc->fc->ioctl(ap)
(fwdev.c:694) -> fwohci_ioctl (fwohci.c:333)`:

* `FWOHCI_WRREG(0x18c, 0xdeadbee0)` — OHCI ATQ **DMA context command
  pointer** — rc=0, value stuck in the register file (root cross-check
  via the rig: `MMIO[0x18c]=0xdeadbee0`)
* `FWOHCI_WRREG(0x88, 0xdeadbee1)` — FWOHCI_INTMASK (interrupt mask)
* `FWOHCI_WRREG(0x50, 0xdeadbee2)` — OHCI_HCCCTL (link control / reset)
* `FWOHCI_WRREG(0x00, 0xdeadbee3)` — even the version register
* `FWOHCI_RDREG` read every value back; `FWOHCI_WRPHYREG` /
  `FWOHCI_RDPHYREG` executed the full PHY access sequences unprivileged

No EPERM anywhere. Note: `fwdev.c:694` discards `fc->ioctl()` return
values, so even the `addr > 0x800` EINVAL of fwohci.c:360 never reaches
userspace (the write is still not executed — bounds check works, error
report does not).

## Rig
The established FireWire verbatim-interposition harness extended to the
OHCI side (`fwohci_harness.c`): fwohci.c compiled unmodified into the
harness TU; an emulated MMIO register file stands in for the card
(on x86_64 `bus_space_read_4/write_4` are direct KVA dereferences,
sys/cpu/x86_64/include/bus_dma.h:130-162, so `sc->bst=MEM, sc->bsh=&regs`
gives the real OWRITE/OREAD a live register file); /dev/fw0.0 is created
against the stock `firewire_ops` with stock clone permissions
(0660 root:operator).

## Reachability honesty
* On real hardware the writable range [0x000,0x800] covers the entire
  OHCI register file including the DMA ContextCommand/CommandPtr
  registers: an operator-group user can point AT/AR/IR/IT contexts at
  attacker-chosen physical addresses, i.e. the classic FireWire
  arbitrary-physical-memory read/write primitive on non-IOMMU systems,
  plus controller reset (DoS) and PHY bus disruption. Gate: operator
  group membership + a FireWire controller (driver auto-attaches on
  hardware; /dev/fw* clones appear on open).
* On this QEMU guest there is no OHCI hardware; the register file is
  the rig emulation. The *code path* is 100% stock, so the missing
  privilege gate is proven mechanically; the hardware impact ceiling is
  assessment, not measurement.
* Guest has no IOMMU-relevant config; PRIVESC ASSESSMENT: on real
  hardware this is a plausible unpriv->root path (DMA to kernel text/
  cred memory). It is not demonstrable on the hardware-less guest; the
  finding stays Medium (operator-gated, hardware-gated) but should be
  treated as privesc-class on workstations with FireWire ports.

## Fix
fix.diff adds `caps_priv_check(ap->a_cred, SYSCAP_NODRIVER)` (the DF
driver-hardware capability gate, cf. sio.c usage) to fwohci_ioctl.
A/B validated: patched kernel -> opuser ioctls execute no register
access (register file unchanged, PHY untouched); root still allowed.
