DF-3691 / verdict.json
{ "finding_id": "DF-3691", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "No parser validates raid->width against MAX_DISKS; total_disks and width are independent metadata fields, so a checksum-valid Promise/FreeBSD RAID0 array with total_disks=1 (READY with one online disk) and width=64 assembles at boot, and the first kernel I/O (MBR slice scan) computes drv=(blkno/interleave)%width=blkno%64, indexes rdp->disks[32+].dev OOB and dereferences the OOB-read pointer (NULL from zeroed heap) in device_get_softc - fatal page fault at boot, no user interaction. RAID1/01 variants additionally OOB-WRITE disks[width].last_lba (user-chosen 64-bit value) and composite->request[this] (kernel pointer) per source analysis; RAID0 path used for the deterministic demo. Width sources include a 16-bit Adaptec field (up to 65535).", "exploit_chain": "crafted disk (Promise-native RAID0, width=64) -> array READY at boot -> kernel slice-scan bio -> drv = blkno%64 >= 16 -> rdp->disks[drv].dev read OOB -> wild/NULL device_t deref in ata_raid_send_request -> fatal trap. Exploitation beyond panic (heap-groom the OOB dev into a fake ata_device, or use RAID1 last_lba OOB write) not pursued this run; primitive documented in VERDICT.md.", "evidence": "panic.txt + run.log (fault VA 0x80 = offsetof(device,softc) with dev=NULL), VERDICT.md primitive characterization, run.patched.log (illegal array geometry (width 64), I/O error, boot completes)", "kernel_refs": [ "sys/dev/disk/nata/ata-raid.c:1685", "sys/dev/disk/nata/ata-raid.c:1868", "sys/dev/disk/nata/ata-raid.c:2039", "sys/dev/disk/nata/ata-raid.c:3108", "sys/dev/disk/nata/ata-raid.c:3248", "sys/dev/disk/nata/ata-raid.c:3563", "sys/dev/disk/nata/ata-raid.c:360", "sys/dev/disk/nata/ata-raid.c:400", "sys/dev/disk/nata/ata-raid.c:409", "sys/dev/disk/nata/ata-raid.c:421", "sys/dev/disk/nata/ata-raid.c:504", "sys/dev/disk/nata/ata-raid.c:567", "sys/dev/disk/nata/ata-raid.c:587", "sys/dev/disk/nata/ata-raid.c:943" ], "poc_changes": "built metadata from scratch (mkmeta.py); promise struct offsets verified against real header via guest-compiled layout probe (raid@512, array_width@546, disk[8]@564, checksum@2044); first try worked", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "python3 mkmeta.py (host); image attached as ata0-master at QEMU launch", "run_cmd": "ARAID_DRIVE=/tmp/opencode/araid/f2_width.img dfbsd-qemu/vm.sh up 220", "code_hash": "", "notes": "READY gating for RAID0 loops over total_disks, not width - that asymmetry is what makes the PoC deterministic. RAID1/01 OOB writes need the OOB flags word to read AR_DF_ONLINE (groom-dependent) - documented, not demoed. Distinct from known DF-1174/2496 (div0) and DF-1173/2493/2497 (disk_number/total_disks/SPAN walk).", "recommended_fix": "geometry guard at top of ata_raid_strategy (width 1..MAX_DISKS; RAID1/01 2*width<=MAX_DISKS; RAID5 width>=2 -> EIO) plus clamped RAID1/01 loop in ata_raid_config_changed (fix.diff hunks 3+5)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel, same disk: array still announced at attach but first I/O hits ar0: illegal array geometry (width 64), partition table read fails cleanly with EIO, boot reaches login, no fault. Baseline boot panic gone.", "fix_evidence": "run.patched.log: ar0: illegal array geometry (width 64) + error accessing offset 0 ... for 512 + vm.sh up succeeded (ssh alive)" } |