# DF-2496 — divide-by-zero panics from crafted RAID geometry (nata ata-raid)

## What was verified

`sys/dev/disk/nata/ata-raid.c` copies RAID geometry (interleave, width,
total_sectors, heads/sectors) verbatim from on-disk metadata and uses the
fields as divisors with **no zero check**. All three filed divide sites
were driven to a **deterministic kernel panic (fatal trap 18, integer
divide fault)** on the QEMU guest, each in its own boot:

| site | code | proof |
|---|---|---|
| `ata_raid_strategy` RAID0/01 | `chunk = blkno % rdp->interleave` (ata-raid.c:359, interleave=0 from crafted Intel `stripe_sectors`) | `panic_strategy.txt`: `Fatal trap 18 ... Stopped at ata_raid_strategy+0x2f3: divq %r12,%eax` |
| `ata_raid_status` via REAL `/dev/ata` ioctl | `progress = 100 * rebuild_lba / total_sectors` (ata-raid.c:1028, total_sectors=0 from crafted Intel `total_sectors`) | `panic_status_ioctl.txt`: `Fatal trap 18 ... Stopped at ata_raid_ioctl+0x11b: divq 0x48(%r14),%eax` — IP in the **real kernel built-in ataraid** (0xffffffff803388eb), reached by the real userland `atastat` ioctl |
| `ata_raid_attach` | `total_sectors/(heads*sectors)` (ata-raid.c:181, heads=0; the `rounddown(..., interleave*width)` at :157 is the same class) | `panic_attach.txt`: `Fatal trap 18 ... divq` (attach inlined into the sysctl caller at -O2) |

Setup half (`run_nonfatal.log`, test 12): the production
`ata_raid_intel_read_meta()` accepts crafted metadata with
`stripe_sectors=0` **and** `total_sectors=0` and installs an `AR_S_READY`
RAID0 array with `interleave=0, total_sectors=0` — no parser validation.

## Build / run (guest, root; requires `vm.sh reset with-src`)

```
cd /root/dfrig3 && ./build.sh     # KLD: production ata-raid.c #included verbatim
kldload ./dfrig3_ata.ko
sysctl kern.dfrig3_ata_test=12    # non-fatal: install degenerate geometry, print it
sysctl -n kern.dfrig3_ata_status
sysctl kern.dfrig3_ata_test=20    # FATAL: strategy divide (panic on serial)
# separate boots:
sysctl kern.dfrig3_ata_test=21    # arm REAL ata_raid_arrays[0], then:
/root/dfrig3/atastat 0            # FATAL: real ioctl hits status divide
sysctl kern.dfrig3_ata_test=22    # FATAL: attach divide
```

Expected (baseline): tests 20/21/22 each end in `Fatal trap 18: integer
divide fault while in kernel mode` on the serial console (guest dead at
`db>`).

## Fix validation

`fix.diff` guards all sites (strategy RAID0/01/5 geometry check →
`biofinish(EIO)`, `status->progress` ternary, attach rounddown/ncylinders
ternaries). Single-fix kernel built with `nativekernel` (see
`fix_build.log`), rig rebuilt against the fixed source; `fix_validation.log`
shows tests 20/21/22 all SURVIVING on the patched kernel:
`ar0: degenerate RAID0/01 geometry (interleave=0 width=2)` +
`rig_bio_done b_error=5`, attach completes, and the exact ioctl that
panicked the baseline returns `atastat: ok ... progress=0`.
