DF-3690 / manifest.json
{ "finding_id": "DF-3690", "verdict": { "finding_id": "DF-3690", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Adaptec HostRAID parser copies an untrusted 16-bit total_disks into raid->total_disks and, because raid->generation is assigned from the same metadata before it is tested, executes the disks[]-clearing loop on the FIRST parse: with total_disks=60000 the kernel wrote NULL/0 across ~2.8MB of heap during ata_raid_subdisk_attach and fatally hit a kernel stack guard page (panic captured on the guest, boot from a single crafted disk, zero interaction). Primitive = attacker-chosen-length strided zeroing write starting inside a live ar_softc; demonstrated as reliable persistent DoS / heap corruption.", "exploit_chain": "crafted disk image with Adaptec metadata (total_disks=60000, gen=1) -> attach at boot -> parse loop writes disks[n].dev=NULL/.flags=0 for n<60000 -> heap + stack guard page smashed -> fatal kernel page fault (DDB wedge). Escalation beyond DoS not pursued: the write content is fixed (NULL/0), value control is absent; realistic ceiling is adjacent-object pointer NULLing (corruption), demonstrated ceiling is boot-time panic.", "evidence": "panic.txt (fatal trap + ata_raid_subdisk_attach frame), run.log, VERDICT.md 'Why it happens', run.patched.log (fix rejects with 'Adaptec total_disks out of range', boots to login)", "kernel_refs": [ "sys/dev/disk/nata/ata-raid.c:1704", "sys/dev/disk/nata/ata-raid.c:1703", "sys/dev/disk/nata/ata-raid.c:1716", "sys/dev/disk/nata/ata-raid.c:1717", "sys/dev/disk/nata/ata-raid.c:1720", "sys/dev/disk/nata/ata-raid.h:108" ], "poc_changes": "Seed-free pass-2 finding. First image attempt used big-endian magics and two wrong struct offsets (adaptec magics are raw native compares, unlike generation); guest-compiled layout2.c against the real header fixed the offsets and the image then parsed and panicked as predicted.", "attempts": 2, "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": 330, "guest_dirty": 0, "build_cmd": "python3 mkmeta.py (host) ; disk attached via QEMU ide.0 unit=0 at launch", "run_cmd": "ARAID_DRIVE=/tmp/opencode/araid/f1_adaptec.img dfbsd-qemu/vm.sh up 220", "code_hash": "", "notes": "ata_raid_adaptec_print_meta also loops to be16toh(total_configs) over configs[127] (bootverbose only) - noted, not fixed. Fix validated on rebuilt kernel (#1 Sep 15 17:27): no array, plain ad0, boot completes.", "recommended_fix": "reject be16toh(configs[0].total_disks) > MAX_DISKS in ata_raid_adaptec_read_meta before any use (fix.diff hunk 6)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel (nativekernel rebuild with fix.diff): same crafted disk prints 'Adaptec total_disks out of range', creates no array, ad0 attaches as a plain disk, boot reaches login. Baseline panic gone.", "fix_evidence": "findings/poc/DF-3690/run.patched.log lines: 'ad0: Adaptec total_disks out of range', 'ad0: 127MB <QEMU HARDDISK 2.5+>', normal boot; compare panic.txt" }, "reproduce": { "build": "python3 mkmeta.py (host); attach image as QEMU ata0-master (vm.sh ARAID_DRIVE)", "run": "ARAID_DRIVE=f1_adaptec.img dfbsd-qemu/vm.sh up (panic at parse)", "expected": "panic: vm_fault ... ata_raid_subdisk_attach frame" }, "kernel_refs": [ "sys/dev/disk/nata/ata-raid.c:1704", "sys/dev/disk/nata/ata-raid.c:1716", "sys/dev/disk/nata/ata-raid.c:1720" ], "artifacts": [ "README.md", "VERDICT.md", "mkmeta.py", "build.sh", "run.sh", "run.log", "panic.txt", "run.patched.log", "fix.diff", "env.txt", "verdict.json", "manifest.json" ], "code_hash": "19b6ef7de08eec487c4b3111586d4e9e39dce900a4d6e3c138efa9783daa8f22" } |