DF-5293 / verdict.json
{ "finding_id": "DF-5293", "status": "inconclusive", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "rums instance of the DF-5247 (if_run) / DF-5260 (if_mtw) cmdq-lifetime twin. rum_update_beacon() queues the RAW vap pointer into the deferred command ring (if_rum.c:2830, rum_cmd_sleepable :745-771 only ieee80211_runtask()s it) and the taskqueue later runs rum_update_beacon_cb (:2784-2790) -> rum_set_beacon(sc, data->vap) (:2729) which reads rvp->bcn_mbuf (:2733), vap->iv_txparms (:2744) and streams mtod(m)/m_pkthdr.len bytes to the device (:2754-2755). rum_vap_delete() (:709-721) kfree()s the rum_vap (:720) after draining ONLY rvp->ratectl_task (:717) - sc->cmdq_task is never drained and the ring is never purged, so a queued callback executes on freed (and immediately reusable, M_80211_VAP-zone) memory. Divergences from the twins verified: rums cmdq ring producers DO take RUM_CMDQ_LOCK (:753-766), so the DF-5249/5262 torn-publish bug does not apply; rum_key_set/rum_key_delete copy the key BY VALUE (:3021/:3038), so the DF-5250/5263 raw-key UAF does not apply - the vap pointer at :2830 is the single dangling deferred reference. In-kernel reproduction is hardware-gated (no RT2573 on the QEMU guest). Simulated on the guest with a line-faithful ring+taskqueue+destroyer model: shipped code produced 11599/11849/12071 post-free rum_set_beacon executions across 3x10s runs (~61% of all callbacks), while adding the missing draintask before kfree yields exactly 0/0/0.", "exploit_chain": "beacon-update cmd queued (:2830) -> ifconfig destroy before the backlogged taskqueue runs cmdq_task -> kfree(rvp) (:720) -> rum_update_beacon_cb reads freed rum_vap: bcn_mbuf wild pointer + garbage m_pkthdr.len -> rum_write_multi streams len bytes from a freed-heap-shaped kernel address to the device (over-the-air disclosure in hostap mode) and wild-reads kernel memory -> panic-capable UAF primitive; M_80211_VAP slot reallocation gives the attacker shape control over the freed object", "evidence": "run.log: shipped mode POST-FREE rum_set_beacon=11599/11849/12071, fixed mode =0/0/0; rum_cmdq_uaf.c models the 16-slot ring, raw-pointer producer, dispatch-latency taskqueue and the undrained destroy; VERDICT.md lists the two twin-bugs that were checked and do NOT apply to rum", "kernel_refs": [ "sys/bus/u4b/wlan/if_rum.c:2830", "sys/bus/u4b/wlan/if_rum.c:745", "sys/bus/u4b/wlan/if_rum.c:768", "sys/bus/u4b/wlan/if_rum.c:723", "sys/bus/u4b/wlan/if_rum.c:2784", "sys/bus/u4b/wlan/if_rum.c:2733", "sys/bus/u4b/wlan/if_rum.c:2754", "sys/bus/u4b/wlan/if_rum.c:715", "sys/bus/u4b/wlan/if_rum.c:720" ], "poc_changes": "Harness written from scratch (no seed); pthread-based ring + condvar taskqueue with realistic dispatch latency; poison flag on the vap so post-free cb executions are counted rather than crashing; mode 1 adds the exact draintask-before-kfree the fix proposes", "attempts": 3, "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": 75, "guest_dirty": 0, "build_cmd": "cc -O2 -pthread -Wall -o rum_cmdq_uaf rum_cmdq_uaf.c", "run_cmd": "./rum_cmdq_uaf 10 0 (x3) then ./rum_cmdq_uaf 10 1 (x3)", "code_hash": "a1514a431805bd9c2b774bd5b8e02f5954bb8d075626f78ef9bda92f27491a1f", "notes": "Hardware-gated like the rest of the wlan family this pass (methodology of DF-5246..DF-5267). The fix overlaps DF-5292s in rum_vap_delete (trivial merge, both drain/lock before kfree).", "recommended_fix": "ieee80211_draintask(ic, &sc->cmdq_task) in rum_vap_delete() before kfree(rvp), so queued beacon-update cmds referencing the vap complete first", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored and verified with git apply --check against the pristine sys/ tree; kernel behavior cannot be exercised without an RT2573 device (no USB passthrough/device model on the guest). The userland model demonstrates the fix protocol reduces post-free callback executions from ~61% to exactly 0. Hardware-gated: not_testable.", "fix_evidence": "fix.diff (git-apply clean); run.log fixed-mode lines =0/0/0; VERDICT.md" } |