# DF-2496 VERDICT — reproduced (all three divide sites panic the kernel)

## Bottom line

CONFIRMED at every filed site. The nata RAID parsers copy geometry
fields verbatim from on-disk metadata into the live `struct ar_softc`
and the I/O / status / attach paths then use them as divisors with no
zero check. On the audit guest (DragonFly 6.5-DEVELOPMENT x86_64,
kernel #0 Thu Jul 2 2026), crafted Intel metadata
(`stripe_sectors=0`, `total_sectors=0`) and a crafted JBOD geometry
(`heads=0`) each produced a **deterministic fatal trap 18 (integer
divide fault)**, one per boot:

1. **strategy** (`sys/dev/disk/nata/ata-raid.c:359`): production
   `ata_raid_intel_read_meta()` (rig test 20) installs
   `type=AR_T_RAID0, status=AR_S_READY, interleave=0`; the production
   `ata_raid_strategy()` then executes `chunk = blkno %
   rdp->interleave` → `Fatal trap 18 ... Stopped at
   ata_raid_strategy+0x2f3: divq %r12,%eax` (`panic_strategy.txt`).
   The RAID5 variants (:366-372, `/interleave`, `%(width-1)`, `%width`)
   are the same class and are covered by the same guard.
2. **status via REAL kernel ioctl** (`ata-raid.c:1028`): the rig's
   production parse (test 21) plants `total_sectors=0` into the REAL
   kernel `ata_raid_arrays[0]` (0xffffffff8114dec0), and a real
   userland `ioctl(IOCATARAIDSTATUS)` on `/dev/ata` (atastat) executes
   the REAL built-in kernel's `ata_raid_status` divide → `Fatal trap
   18 ... Stopped at ata_raid_ioctl+0x11b: divq 0x48(%r14),%eax`
   (`panic_status_ioctl.txt`; IP 0xffffffff803388eb is kernel-base
   built-in code, not the rig module). Full chain: userland syscall →
   /dev/ata → ioctl → attacker-zeroed divisor → fatal trap.
3. **attach** (`ata-raid.c:181`): crafted `heads=0, sectors=63` on an
   `AR_T_JBOD` array (which also skips the `rounddown(:157)` variant)
   → production `ata_raid_attach()` divides by `heads*sectors==0` →
   `Fatal trap 18 ... divq` inlined into the caller
   (`panic_attach.txt`).

Setup half: rig test 12 (`run_nonfatal.log`) shows the production
Intel parse accepting `stripe_sectors=0` AND `total_sectors=0` and
installing a READY RAID0 array — no parser-side validation exists.

## Threat model

Attacker data is on-disk RAID metadata read at subdisk attach (boot or
disk insertion on an nata ATA channel) — no OS privileges needed; the
panic then triggers on the first I/O / status query / attach. On the
standard guest the authentic boot-attach arm is blocked by the QEMU
SeaBIOS/IDE-disk limitation documented in DF-2494, so the production
parser+divide code is driven through the DF-2494 KLD rig (production
`ata-raid.c` compiled in verbatim; only `ata_queue_request` is
interposed to serve the crafted sector). The status site was
additionally proven through the real kernel's own code and a real
userland ioctl.

## Fix validation (single-fix kernel)

`fix.diff` adds: strategy RAID0/01 guard (`!interleave || !width`) and
RAID5 guard (`!interleave || width < 2`) with `biofinish(EIO)`;
`status->progress` ternary on `total_sectors`; attach ternaries for the
rounddown divisor and `heads && sectors`. Kernel rebuilt
(`fix_build.log`), rig rebuilt against the fixed source.
`fix_validation.log`: tests 20/21/22 all survive —
`ar0: degenerate RAID0/01 geometry (interleave=0 width=2)` +
`rig_bio_done b_error=5` (EIO) for strategy; attach completes
(`d_ncylinders=0`); the previously-fatal ioctl returns
`atastat: ok type=4 ... progress=0`. Baseline panics: 3/3; patched: 0/3.

## Kernel references

- `sys/dev/disk/nata/ata-raid.c:359-361` — RAID0/01 `%interleave`, `/interleave`, `/width`
- `sys/dev/disk/nata/ata-raid.c:366-373` — RAID5 `/interleave`, `%(width-1)`, `%width`
- `sys/dev/disk/nata/ata-raid.c:1028` — `100 * rebuild_lba / total_sectors`
- `sys/dev/disk/nata/ata-raid.c:157-158` — `rounddown(total_sectors, interleave*width)`
- `sys/dev/disk/nata/ata-raid.c:181` — `total_sectors/(heads*sectors)`
- `sys/dev/disk/nata/ata-raid.c:2229,2231` — Intel parse copies stripe_sectors/total_sectors verbatim

## 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.
