# DF-1083 — reproduce

## Bug
Off-by-one in the `CROM_MAX_DEPTH` guard of `crom_next()`,
`sys/bus/firewire/fwcrom.c:115`.  At `cc->depth == 9` the test
`9 >= 10` is false, so the guard does NOT fire; `depth` is incremented
to 10 and `&cc->stack[10]` (valid indices are 0..9) is written with a
16-byte `struct crom_ptr` — an out-of-bounds **kernel stack** write.

## Why a harness (no live kernel trigger)
The Configuration-ROM parser is reached only when the kernel attaches a
FireWire device (SBP-2 target).  The QEMU audit guest has no FireWire
controller, so the live code path cannot be exercised.  Instead the
harness compiles the **verbatim** `crom_init_context`/`crom_get`/`crom_next`
(fwcrom.c:62-143) and the exact structures (iec13213.h) and feeds them a
crafted 10-deep-nested IEEE-1212 Configuration ROM — the same bytes the
kernel receives from an external FireWire device.

FireWire **is** compiled into GENERIC (`device firewire`/`device sbp`;
`crom_next` is statically linked at `0xffffffff804bdc90`), so the bug
ships in every default kernel.  The three callers in
`sys/dev/disk/sbp/sbp.c:405,549,595` use `struct crom_context cc` as a
**local stack variable** — so the OOB write lands on the kernel stack,
corrupting the return address / saved frame.

## Build
```
cc -O0 -g -o harness harness.c
```

## Run
```
./harness
```

## Expected (bug present — unpatched fwcrom.c)
Exit code 1.  Output ends with:
```
>>> BUG CONFIRMED: crom_next wrote &stack[10] OUT OF BOUNDS.
```
The overflow slot (`&cc.stack[10]`, immediately past the array) is
overwritten: `.dir` becomes a pointer into the crafted ROM, `.index`
becomes 0.

## Expected (fixed — fwcrom.c with `>= CROM_MAX_DEPTH - 1`)
Exit code 0.  Output contains:
```
crom_next: too deep
>>> canary intact: no OOB write (guard fired correctly).
```

## Fix
`fix.diff`: change line 115 from `>= CROM_MAX_DEPTH` to
`>= CROM_MAX_DEPTH - 1`.  At depth 9 the test `9 >= 9` is true, the
guard fires, and the descent to depth 10 / `stack[10]` never happens.
