DF-3981 / verdict.json
{ "finding_id": "DF-3981", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "sbp(4) arms sdev->login_callout (sbp.c:649-650, up to login_delay=1000ms, auto_login default on) but never stops it on the three sbp_dev free paths: sbp_alloc_lun stale-LUN invalidation (sbp.c:444-445), the trailing !VALID_LUN loop (sbp.c:534-541), and sbp_post_explore GC -> sbp_free_target -> sbp_free_sdev (sbp.c:776-786, 816-817, 1978-1990, kfree at 1989; the only stop in the whole driver is sbp_logout_all sbp.c:1959, shutdown-only). A hostile FireWire device controls its Config ROM LUN set and bus-reset timing, so it can free an sdev while the callout is armed; sbp_login_callout (sbp.c:625-629) then calls sbp_mgm_orb() on the kfreed sdev: freed-slab reads (sdev->target, free_ocbs head), writes into freed slab (ocb->flags/sdev) and into fwdma_freed ORB pages (orb[0..7]) plus a re-armed mgm_ocb_timeout on the dangling ocb - kernel heap use-after-free read+write, deterministic attacker timing. End-to-end inconclusive only because the audit guest has no FireWire OHCI controller (pciconf, env.txt); the core mechanism - the DragonFly callout subsystem firing a callback on a kfreed container - was PROVEN live on the guest kernel twice on two boots via mechanism replica A (run.log: login_callout FIRED on FREED object 0xfffff80117817880, arg == freed pointer: YES).", "exploit_chain": "crafted FireWire device: present LUN N (ROM CROM_LUN) -> probe arms login_callout (<=1s) -> device forces bus reset and re-presents ROM without LUN N -> sbp_post_explore/sbp_alloc_lun kfree(sdev) with callout armed -> softclock fires sbp_login_callout on freed slab -> sbp_mgm_orb UAF: slab-recycled reads drive pointer walks; orb writes land in freed (reusable) DMA pages; mgm timeout re-armed on dangling ocb -> subsequent status write by the attacker completes through freed state -> heap corruption / panic.", "evidence": "VERDICT.md (full path:line analysis); run.log (mechanism A output, two boots); build.log (module built on guest /usr/src); env.txt (no OHCI-1394 on guest); fix.diff (callout_stop in sbp_free_sdev + scan_callout/slot-release in sbp_free_target, applies cleanly)", "kernel_refs": [ "sys/dev/disk/sbp/sbp.c:183", "sys/dev/disk/sbp/sbp.c:625", "sys/dev/disk/sbp/sbp.c:649", "sys/dev/disk/sbp/sbp.c:444", "sys/dev/disk/sbp/sbp.c:536", "sys/dev/disk/sbp/sbp.c:776", "sys/dev/disk/sbp/sbp.c:1978", "sys/dev/disk/sbp/sbp.c:1989", "sys/dev/disk/sbp/sbp.c:1993", "sys/dev/disk/sbp/sbp.c:1959" ], "poc_changes": "No runnable end-to-end PoC possible (no FireWire hardware in guest). Wrote a kernel mechanism replica instead: kmallocd container + armed callout + kfree, callback reports firing on the freed pointer without dereferencing (guest-safety); requires callout_init (not CALLOUT_INIT, which is a firewire-internal alias) and DFlys 10-arg SYSCTL_ADD_PROC.", "attempts": 2, "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": 240, "guest_dirty": 0, "build_cmd": "cd /root/kmod && make", "run_cmd": "kldload ./sbpprep.ko && sysctl kern.sbpprep_a=1 && sleep 4 && dmesg | grep sbpprep[A]", "code_hash": "c4245b4d7304e28974191235a02ccdcf60287b38fd2b76e8e7b2974689a8bda5", "notes": "Same-module mechanism B (blocking callout_stop) is filed as DF-3982 with its own evidence. Guest was reset with-src after the runs (clean hand-off).", "recommended_fix": "callout_stop(&sdev->login_callout) at the top of sbp_free_sdev; also stop scan_callout and clear fwdev in sbp_free_target even when luns==NULL (fix.diff in pack).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored from line-accurate source analysis; applies cleanly (patch --dry-run verified). Cannot be kernel-build validated on this guest: the trigger path needs FireWire hardware, so a patched-kernel run has no observable delta here.", "fix_evidence": "fix.diff (callout_stop additions; slot-release restructure of sbp_free_target)" } |