DF-5328 / verdict.json
{ "finding_id": "DF-5328", "status": "not_reproduced", "reproduced": false, "impact": "none observed; code-level race: camperiphfree() can free the periph inside cam_periph_alloc()s find()->flag-store window (UAF write into freed 144B M_CAMPERIPH chunk) and camperiphfree() can observe CAM_PERIPH_NEW_DEV_FOUND with an unpublished NULL deferred_callback -> indirect call through NULL/garbage", "confidence": "likely", "verdict": "cam_periph_alloc() touches periph->flags/deferred_callback/deferred_ac unlocked on the borrowed cam_periph_find() result; camperiphfree() (buses-locked remove + dtor + kfree, plus the flag read at :604) is not serialized against those stores. Bounded guest race (200 invalidate/rescan cycles x 4000 open/close churns, 90s) produced no hit -- the window is a few instructions wide and requires the dying periphs last reference to drop exactly as a rescan rediscovers the LUN (hot-plug/close race). Finding stands on the lock-domain analysis; not demonstrated at runtime.", "exploit_chain": "", "evidence": "VERDICT.md (full interleaving analysis), race.log (bounded attempt, no anomalies), README.md", "kernel_refs": [ "sys/bus/cam/cam_periph.c:176", "sys/bus/cam/cam_periph.c:180", "sys/bus/cam/cam_periph.c:181", "sys/bus/cam/cam_periph.c:182", "sys/bus/cam/cam_periph.c:292", "sys/bus/cam/cam_periph.c:305", "sys/bus/cam/cam_periph.c:604", "sys/bus/cam/cam_periph.c:625", "sys/bus/cam/cam_periph.c:630" ], "poc_changes": "race rig built from the evilcd2 rig (invalidate/rescan sysctls already present); no seed existed", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Fri Oct 2 21:19:55 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/EVIL x86_64", "runtime_sec": 95, "guest_dirty": 0, "build_cmd": "cc -O -o race_fdchurn race_fdchurn.c", "run_cmd": "sh race_alloc.sh # ~90s bounded loop", "code_hash": "2f1a831faec17fe2da1552b020a69488357f4e5e383d2ae19f5961374370e388", "notes": "window measured in instructions on the allocating thread; cannot be widened without patching sys/ (out of verification scope). FreeBSD restructured this area; DFly retains the borrowed-pointer pattern.", "recommended_fix": "perform the units-list lookup and the deferred bookkeeping under one xpt_lock_buses() hold, storing deferred_callback/deferred_ac BEFORE the NEW_DEV_FOUND flag (fix.diff)", "fix_status": "not_testable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "fix.diff authored from the analysis; not kernel-validated (race not reproduced at runtime)", "fix_evidence": "fix.diff; VERDICT.md lock-domain analysis" } |