# DF-2294 VERDICT — REPRODUCED (panic, local DoS, operator-group user)

## Chain (line-accurate, stock fwdev.o)
`fw_ioctl` (fwdev.c:410) takes `ir = d->ir` at fwdev.c:443 — NULL until
a successful FW_SRSTREAM (fwdev.c:494). Neither bind ioctl checks it.

### FW_SBINDADDR (fwdev.c:603-634)
```c
612:	fwb = kmalloc(sizeof (struct fw_bind), M_FW, M_WAITOK);
613:	fwb->start = ((u_int64_t)bindreq->start.hi << 32) | bindreq->start.lo;
615:	fwb->end = fwb->start +  bindreq->len;
617:	fwb->sub = ir->dmach;            <-- ir == NULL: load at 0x10
```
Observed: `Fatal trap 12: page fault`, `fault virtual address = 0x10`,
`supervisor read data, page not present`, `fw_ioctl() at fw_ioctl+0x6eb`
← `dev_dioctl` (panic.sbindaddr.txt). 0x10 == offsetof(struct
fw_xferq, dmach) on this build — exactly the predicted
NULL+offsetof dereference. Single open + single ioctl.

### FW_CBINDADDR (fwdev.c:592-602)
```c
593:	fwb = fw_bindlookup(sc->fc, bindreq->start.hi, bindreq->start.lo);
595:	if(fwb == NULL){ err = EINVAL; break; }   <-- guards only the miss
599:	STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
600:	STAILQ_REMOVE(&ir->binds, fwb, fw_bind, chlist);  <-- NULL+0x38
```
Reaching :600 requires a matching bind to exist, which (via the stock
code) can only be registered by an fd whose own `d->ir` is set. The
reproducer therefore uses two fds on the same controller: fd1 does the
legit SSTBUF+SRSTREAM+SBINDADDR setup (real `fw_bindadd`,
firewire.c:820), fd2 (fresh open, `d->ir == NULL`) issues FW_CBINDADDR
→ `Fatal trap 12`, `fault virtual address = 0x38`
(== offsetof(struct fw_xferq, binds)), `fw_ioctl+0x429`
(panic.cbindaddr.txt).

Both panics: uid=1002 opuser (operator group). No FireWire bus
activity required.

## Reachability honesty
Same as DF-2293: 0660 root:operator nodes exist only on systems with
an OHCI controller (stock GENERIC compiles firewire but not fwohci).
Verification used the verbatim-interposition harness; the faulting
binary is the stock fwdev.o.

## Fix validation (A/B, fix.diff FW_CBINDADDR/FW_SBINDADDR guards)
Patched kernel:
* poc_2294 sbind → `ioctl rc=-1 errno=22`, no panic
* poc_2294 cbind → fd1 setup still succeeds (legit bind path intact),
  fd2 FW_CBINDADDR → `ioctl rc=-1 errno=22`, no panic
* guest alive.

## Privesc assessment
None — NULL-offset load/store, deterministic fault → panic. Impact:
dos. (The faulting *write* at &ir->binds in FW_CBINDADDR is a store to
a fixed low address; on this kernel it simply faults — no controlled
write primitive.)

## Artifacts
panic.sbindaddr.txt, panic.cbindaddr.txt, run_fixed.log, poc_2294.c,
fwharness.c (rig), env.txt.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
