DF-5593 / verdict.json
{ "finding_id": "DF-5593", "status": "reproduced", "reproduced": true, "impact": "leak", "confidence": "certain", "verdict": "cam_sim_release()s final branch (cam_sim.c:246-252) drops the devq and kfrees the sim without draining sim->ccb_freeq: every ccb pooled by xpt_get_ccb/xpt_release_ccb (cam_xpt.c:4958-4975/4247-4271) is orphaned at controller detach. Measured on the stock guest with the ptsim3 rig: sim->ccb_count=8, ccb_freeq length=8 reported at the detach; vmstat -m CAM_XPT count 40 -> 69 across the scan with zero return after the clean deregister+free. Deterministic, permanent kernel heap leak (~0.75-1KB per pooled ccb) per controller detach after I/O (kldunload, hot-plug, surprise removal); repeated cycles exhaust kernel memory.", "exploit_chain": "", "evidence": "run.log (DF-5593: sim->ccb_count=8, ccb_freeq length=8 ... 8 ccbs orphaned + vmstat CAM_XPT before/after); VERDICT.md; ptsim3.c mode 3", "kernel_refs": [ "sys/bus/cam/cam_sim.c:241-256", "sys/bus/cam/cam_xpt.c:4958-4975", "sys/bus/cam/cam_xpt.c:4247-4271", "sys/bus/cam/cam_xpt.c:5156", "sys/bus/cam/cam_sim.h:133-140" ], "poc_changes": "mode 3 of the DF-5592 rig (same build); no additional changes", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "sh build.sh (in guest /root/df5592; builds ptsim3/ptsim3.ko)", "run_cmd": "kldload ./ptsim3/ptsim3.ko; vmstat -m > b; sysctl debug.ptsim3.scan=1; sleep 3; sysctl debug.ptsim3.go=3; vmstat -m > a; diff b a", "code_hash": "ac2b604d727bb3aa794653c523e00e54cb2279eab77c82e9f42b5a994c71debb", "notes": "First deregistration attempt with 8 attached da periphs wedged inside xpt_bus_deregister teardown (destroy_dev under sim lock -- unrelated rig noise); noattach mode produced the clean, completed detach used for the measurement", "recommended_fix": "Drain sim->ccb_freeq (SLIST_REMOVE_HEAD + xpt_free_ccb + ccb_count--) in cam_sim_release()s final branch before kfree(sim)", "fix_status": "not_tested", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "leak-class finding: recommended one-block drain slots into the same final branch validated by DF-5592s rebuilt kernel; not separately rebuild-validated in this run", "fix_evidence": "README.md fix snippet; DF-5592 fix_run.log exercises the same free path" } |