# DF-2495 VERDICT — reproduced (1912-byte kernel-heap OOB write out of production `ata_raid_status()`), with an honest impact ceiling

## Bottom line

The pass-1 claim is real at the code level and reproduced through production
code twice; its *practical* trigger surface on this tree is narrower than
filed (details below).

**The write.** `ata_raid_lsiv2_read_meta()` sets
`raid->total_disks = meta->configs[raid_entry].raid.disk_count`
(`ata-raid.c:2856`) — a raw `u_int8_t` from the crafted `$XIDE$` superblock,
no bound against `MAX_DISKS=16`. Every later loop trusts it. The one that
writes is `ata_raid_status()` (`ata-raid.c:1013-1025`):

```c
for (i = 0; i < rdp->total_disks; i++ ) {
    status->disks[i].state = 0;          /* unconditional OOB store */
    ... status->disks[i].lun = -1; ...
}
```

`status` is the generic ioctl layer's copyin buffer: 152 bytes, and because
152 > `STK_PARAMS` (128) `kern_ioctl` kmallocs it (`sys/kern/sys_generic.c:664-680`).
With `total_disks=255` the loop writes 2064 bytes — **1912 bytes past the
allocation** — with the production pattern `{state=0, lun=-1}` per entry.

**Reproduced:**
- *rig test 3* (guard-buffer proof): production parse → `rdp->total_disks=255`
  installed in the module's real `ata_raid_arrays[0]`; production
  `ata_raid_status()` called with a 152-byte kmalloc'd buffer surrounded by
  0xAA guard chunks → 12/24 guards smashed, victim tail overwritten with
  `ffffffff00000000` words (run.log).
- *real-kernel arm*: rig test 7 ran the same production parse with
  `raidp` = the REAL kernel `ata_raid_arrays` (0xffffffff8114dec0), then the
  REAL `/dev/ata` `IOCATARAIDSTATUS` ioctl (`df2495_status`, ordinary
  `ioctl(2)` through `ata-all.c:443 → ata_raid_ioctl:249 → ata_raid_status`)
  returned 0 with `total_disks=255` — i.e. the real kernel executed all 255
  iterations and wrote the 1912 OOB bytes into its own heap.

**No panic observed**: across the single-shot run plus a 3x700-iteration
hammer with concurrent heap churn, the smashed zone neighbors were free
chunks every time. The write primitive is proven; crash/escalation was not
achieved on this guest.

## Honest impact ceiling (differs from the filing)

1. `/dev/ata` is `crw------- root operator` (mode **0600**,
   `ata-all.c:1025` `make_dev(&ata_ops, 0, UID_ROOT, GID_OPERATOR, 0600, ...)`)
   — the filing's "reachable by operator-group" does not hold on this tree:
   **the ioctl arms (STATUS and CREATE) are root-only**. As a privilege
   escalation this is therefore inert here; as a memory-corruption defect it
   remains real (root actions on attacker-inflated state, plus the fsck-style
   "admin runs atacontrol status" confused-deputy pattern).
2. The unprivileged half of the chain is the crafted-disk metadata:
   `disk_count=255` inflates `total_disks` at boot **without any ioctl**.
   The boot-time writers over the inflated count (`ata_raid_config_changed`
   `ata-raid.c:924-926` clears `AR_DF_ONLINE` bits up to 255 entries past the
   `disks[16]` table — an OOB heap read-modify-write at attach; the attach
   print loop at 194-232 OOB-reads the same range) could not be armed on the
   standard guest for the same infrastructure reason as DF-2494: **any IDE
   hard disk hangs SeaBIOS on the vm.sh invocation** (verified with a benign
   image too).
3. The CREATE arm (`ata-raid.c:1051-1151`) does read `config->disks[disk]`
   past the 88-byte struct once `disk >= 16` and can write `-1` at
   `config->disks[disk]` (1148) — but the loop only advances past disks whose
   `devclass_get_device()` lookup succeeds, so with ≤16 subdisk units in the
   system the OOB iterations hit stale-stack garbage, fail the lookup, and
   the single `-1` store lands inside the 128-byte `STK_PARAMS` stkbuf.
   Missing-bound defect confirmed at code level; not weaponized further.

## Fix validation

`fix.diff` (1) rejects `disk_count > MAX_DISKS` at the LSI v2 parse before
the array is accepted, (2) bounds `rdp->total_disks` in `ata_raid_status()`
(defense in depth for arrays inflated by any other parser), and (3) rejects
`config->total_disks` outside `[1, MAX_DISKS]` in `ata_raid_create()`.
Validated on a single-fix rebuilt kernel (fix_build.log / fix_run.log):
the parse now rejects the crafted `disk_count=255` (rc=0), no array is
installed in the real `ata_raid_arrays`, and the STATUS ioctl returns ENXIO.

## Kernel references

- `sys/dev/disk/nata/ata-raid.c:2856` — `raid->total_disks = disk_count` (unvalidated u8)
- `sys/dev/disk/nata/ata-raid.c:1013-1025` — `ata_raid_status` OOB write loop
- `sys/dev/disk/nata/ata-raid.c:1051-1053, 1148` — `ata_raid_create` unchecked `config->total_disks`
- `sys/dev/disk/nata/ata-raid.c:924-926, 194` — boot-time inflated-`total_disks` loops (config_changed RMW / attach prints)
- `sys/kern/sys_generic.c:664-680` — 152-byte ioctl payload kmalloc (`STK_PARAMS=128`)
- `sys/dev/disk/nata/ata-all.c:1025` — `/dev/ata` created 0600 root:operator
- `sys/sys/nata.h:440-483` — `ata_ioc_raid_config.disks[16]` / `ata_ioc_raid_status.disks[16]`

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