⬢ DragonFlyBSD Kernel Audit
DF-3690 / verdict.json
← back to finding ↓ download raw
{
  "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"
}