DF-2426 / verdict.json
{ "finding_id": "DF-2426", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "The divide-by-zero at amd.c:683 is real and mechanically proven on the verbatim driver through the real amd_action(): block_size=0 traps in the inner division (Fatal trap 18, Stopped at amd_action+0x16d: idivq) and block_size=2MiB traps in the outer division (Fatal trap 18, amd_action+0x178: divq). Reachability of the exact userland route claimed in the finding is only half true on this tree: xpt_action filters block_size==0 at cam_xpt.c:3062 before the SIM ever runs, so the as-filed block_size==0 form is unreachable from pass(4) CAMIOCOMMAND; however any block_size over 1MiB (e.g. 2097152) passes that filter, reaches amd_action, and panics - a real privileged-local DoS on machines with an AMD53c974 HBA (PCI 1022:2020) plus a pass(4) node (0600 root:operator). No unprivileged route and no route at all without the HBA; the block_size==0 form is defense-in-depth. Fixed kernel returns CAM_REQ_CMP_ERR for both forms with the control unchanged.", "exploit_chain": "open /dev/passN on the amd bus (root or operator) -> CAMIOCOMMAND with XPT_CALC_GEOMETRY CCB, block_size=2097152, volume_size nonzero -> xpt_action filter (cam_xpt.c:3062) passes because both fields are nonzero -> (*(sim->sim_action))(sim, ccb) (cam_xpt.c:3070) -> amd_action XPT_CALC_GEOMETRY -> (1024L*1024L)/2097152 == 0 -> volume_size/0 -> Fatal trap 18, kernel panic (local DoS; no memory-corruption primitive).", "evidence": "panic0.txt lines 40-60: Fatal trap 18 integer divide fault, Stopped at amd_action+0x16d: idivq %rsi,%eax (block_size=0). panic_big.txt: Fatal trap 18, Stopped at amd_action+0x178: divq %rsi,%eax (block_size=2MiB, the XPT-filter-passing form). run.log: control block_size=512 -> CAM_REQ_CMP heads=64 secs=32 cylinders=100 on the same path. run_fixed_dmesg.log: fixed kernel rejects both with status=0x04 CAM_REQ_CMP_ERR, no trap, guest up.", "kernel_refs": ["sys/dev/disk/amd/amd.c:683", "sys/bus/cam/cam_xpt.c:3062", "sys/bus/cam/cam_xpt.c:3070", "sys/bus/cam/scsi/scsi_pass.c:474", "sys/bus/cam/cam.c:376", "sys/dev/disk/trm/trm.c:994"], "poc_changes": "The finding sketch had no runnable harness: built the established kernel-compiled verbatim-interposition rig for amd.c (first rig for this driver). amd.c compiled unmodified inside the TU against a fabricated cam_sim/ccb; only xpt_done interposed. Discovered during verification: (1) the stock kernel config enables device amd, so the guest config line is commented out to avoid duplicate globals (same as the DF-2269 cd rig); (2) the XPT core already filters block_size==0 (cam_xpt.c:3062), killing the as-filed route - added the block_size=2MiB trigger which passes the filter and is the actually reachable form; (3) harness constants iterated twice (format-string arg count; tinfo[-1] field offsets) before the clean 0-fail battery.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #6: Mon Oct 19 13:14:51 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 3900, "guest_dirty": 0, "build_cmd": "cd findings/poc/DF-2426 && ./build.sh", "run_cmd": "cd findings/poc/DF-2426 && ./run.sh && ./make_fixed.sh && ./run_fixed.sh", "code_hash": "0f8d806544a25f3cd427a56538e582a56091350161cb8e421453c7507cdcc5d2", "notes": "No apostrophes. Severity recommendation: keep Medium for the reachable block_size over 1MiB form (privileged-local DoS on rare 1990s HBA hardware; CVSS AV:L/AC:L/PR:L context); the as-filed block_size==0 form alone would be Info (XPT-filtered upstream of the SIM). Fix uses cam_calc_geometry() exactly as the sibling Tekram driver trm.c:994 does; A/B validated on guest (baseline kernel #3, fixed kernel #6). Guest reset with-src after the run.", "recommended_fix": "Replace the open-coded division in amd_action XPT_CALC_GEOMETRY with cam_calc_geometry(&pccb->ccg, extended), which returns CAM_REQ_CMP_ERR for block_size==0 and for (1MiB)/block_size==0 (same idiom as trm.c)." } |