DF-5071 / verdict.json
{ "finding_id": "DF-5071", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "Sink-level reproduction on the stock guest kernel (DF-4986/DF-5012/DF-5026 house precedent): a raw D_DISK device wired to the verbatim amrd_strategy (amr_disk.c:166-194) -> amr_submit_bio (amr.c:407-416) -> amr_enqueue_bio (amrvar.h:309) -> amr_startio (amr.c:1155-1188, whose (void) cast at :1171 ignores amr_bio_commands ENOMEM from :1240-1241) topology demonstrates that once AMR_STATE_SHUTDOWN is set (amr_pci.c:395 / amr.c:466) or the adapter stops completing (amr has NO watchdog/timeout for async commands), every bio from an already-open fd parks on sc->amr_bioq forever: amrd_strategy has no SHUTDOWN gate while amrd_open in the SAME file refuses new opens (amr_disk.c:126-127), and even that lone gate is bypassed while another fd holds the disk because diskopen() skips the driver d_open (subr_disk.c:1094) -- both asymmetries shown live. The holder process landed in D0/physstr (biowait), SURVIVED kill -9 (SIGKILL pends), and was released only by an external drain (the poke) with EIO; amr_startup (:338) restored normal completion. Nothing in amr_pci_shutdown/amr_rescan_drives/amr_free ever drains amr_bioq -- the amr_pci.c:383 comment claiming the bioq must be empty is false since only the control device sets AMR_STATE_OPEN (amr.c:430); at detach the queue head itself is kfreed under the parked bios (feeding the DF-2082 in-flight UAF window). With the fix pattern transplanted into the sink (strategy fail-fast mirroring amrd_open + drain on shutdown entry) the same held-fd read returns immediately r=-1 errno=6 (ENXIO): no D-state, no accumulation. The real amr entry is hardware-gated on this guest (no MegaRAID adapter) but the completion topology is driver-side unconditional control flow; the identical shape was previously sink-reproduced for mfi (DF-5012) and ips (DF-5026). Impact ceiling: permanent unkillable-hang DoS for every issuer (whole-system wedge when amrd carries root) on adapter fault/removal or privileged rescan/unload.", "exploit_chain": "", "evidence": "run.log: 2237 D0 physstr df5071_trigger wedgehold + survives kill -9 + poke -- draining 1 parked bio(s) with EIO then process gone; dmesg: AMR_STATE_SHUTDOWN set; amr_bioq NOT drained (0 bio(s) already parked); amrd_strategy has NO shutdown gate; gate asymmetry: freshopen-with-holder fd=3 ok (subr_disk.c:1094 bypass) vs freshopen-no-holder fd=-1 errno=6; run_ab.log: (fixed) draining 4 parked bio(s) with ENXIO + wedgehold: pread@2M r=-1 errno=6 + wedgehold gone (completed)", "kernel_refs": [ "sys/dev/raid/amr/amr_disk.c:166", "sys/dev/raid/amr/amr_disk.c:175", "sys/dev/raid/amr/amr_disk.c:126", "sys/dev/raid/amr/amr_disk.c:181", "sys/dev/raid/amr/amr.c:407", "sys/dev/raid/amr/amr.c:411", "sys/dev/raid/amr/amr.c:1155", "sys/dev/raid/amr/amr.c:1171", "sys/dev/raid/amr/amr.c:1178", "sys/dev/raid/amr/amr.c:1240", "sys/dev/raid/amr/amrvar.h:309", "sys/dev/raid/amr/amr_pci.c:383", "sys/dev/raid/amr/amr_pci.c:394", "sys/dev/raid/amr/amr.c:430", "sys/dev/raid/amr/amr.c:466", "sys/kern/subr_disk.c:1094" ], "poc_changes": "authored fresh from source analysis (no seed); three iterations were needed: (1) sim_startio originally looped forever on an empty queue (inverted havecmd semantics vs the real amr_startio break-on-ac==NULL) and wedged the guest -- fixed to the faithful translation; (2) control offsets initially sat at EOF for the declared media so toggles never reached strategy; (3) the parked counter originally counted submissions, not queued bios (re-ran both variants with truthful counts). Control plane lives on a separate ungated char device so the demo self-drives while amrd_opens verbatim gate stays on the raw disk.", "attempts": 5, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 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": 900, "guest_dirty": 0, "build_cmd": "sh build.sh (make KMOD df5071 + df5071f + cc df5071_trigger.c) on the guest", "run_cmd": "sh run.sh (wedge + kill -9 + poke + gate asymmetry); sh run_ab.sh (A/B original vs fixed); patch -p1 + make in /usr/src/sys/dev/raid/amr (fix_validation.log)", "code_hash": "4c673a1d86fbfe4913dcc640ccf5fccbdd3fab56b4a752c1dc8b0b22da296a86", "notes": "Pass-2 finding on sys/dev/raid/amr/amr_disk.c (last LD sibling; family checklist item b). DF-2082 (in-flight-command UAF in amrd_intr) NOT re-reported. Negative results for the rest of the checklist: (d) dump is honest -- amr_std_poll_command has a bounded poll and returns EIO on timeout (amr.c:1347-1363), amr_dump_blocks propagates real status (:2376-2378), no DF-5027 fake-success shape; (e) amrd exposes no ioctls (dev_ops is open/strategy/dump only, amr_disk.c:90-95); amrd_attach has no failure paths; amrd_open ENXIO paths correct. Low-severity note (not filed as separate finding, folded into the audit record): amr.c:1287 truncates the 64-bit bio_offset quotient into the 32-bit mailbox mb_lba and the beyond-EOF check at amr.c:1288-1293 is PRINT-ONLY (no enforcement) -- reachable only by privileged raw-disk I/O, firmware backstop assumed.", "recommended_fix": "amrd_strategy: fail-fast (B_ERROR/ENXIO/b_resid/biodone) when amrd_controller->amr_state & AMR_STATE_SHUTDOWN, mirroring amrd_open; add amrd_fail_queued_bios() and call it from amr_pci_shutdown and amr_rescan_drives after AMR_STATE_SHUTDOWN is set (fix.diff, 4 files, amr.ko compile-validated).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Behavioral A/B at sink level (run.log vs run_ab.log): baseline pattern wedges unkillably (D-state survives SIGKILL, released only by external drain); fixed pattern (strategy fail-fast mirroring amrd_open + drain-on-shutdown) returns ENXIO immediately with no residual process and no accumulation (4 incidental bios drained at shutdown entry). fix.diff also applied to the guests /usr/src (amr_disk.c, amrvar.h, amr.c, amr_pci.c) and compile-validated: full amr.ko rebuilt with -Werror clean including the patched amr_disk.o (fix_validation.log; sources restored pristine). The real amr entry is hardware-gated on this guest; the demonstrated failure mode and its removal are properties of the driver-side completion topology.", "fix_evidence": "run_ab.log ((fixed) draining 4 parked bio(s) with ENXIO + wedgehold: pread@2M r=-1 errno=6 + wedgehold gone (completed)); fix_validation.log (patched amr.ko -Werror clean); fix.diff" } |