DF-3328 / verdict.json
{ "finding_id": "DF-3328", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "certain", "verdict": "hwmp_recv_perrs propagation buffer is allocated without M_ZERO (ieee80211_hwmp.c:1743-1748) and pperr->perr_ttl is never initialized - the only write is the decrement at :1823 before hwmp_send_perr broadcasts the frame - so hwmp_add_meshperr (:784) transmits one byte of prior kernel heap contents as the PERR TTL to the whole mesh. Proven on the guest: across 18 forwarded PERRs, 16 distinct injected rx TTLs (5,9,200,77,250,3,100,55,240,9,88,150,21,66,111,90,12,42) and 3 boots (plus the DF-3327-patched kernel), every emitted TTL byte was 0xfe (== heap 0xff minus the decrement) and never rx_ttl-1; the value matches no byte of any injected frame.", "exploit_chain": "auto-peered attacker sends (1) HWMP PREP origaddr=victim ttl=1 targetaddr=Y -> VALID route Y with nexthop=attacker (hwmp.c:1427-1513); (2) HWMP PERR dest=Y dest_flags=62 (== REASON_MESH_PERR_NO_FI in the misplaced switch, cf. DF-0353) dest_seq=0 ttl>1 -> PERR accepted+forwarded (hwmp.c:1756-1824) -> broadcast PERR whose TTL byte = uninitialized heap; captured via fwm_tx log; repeatable at ~10 Hz (perrminint 100 ms).", "evidence": [ "leak_sample.txt: 18 forwarded-PERR TTL extractions across 3 boots + fixed kernel - always 0xfe, never rx_ttl-1", "run.log / run.2.log / run.3.log: full sysctl transcripts incl. hex dumps of the 43-byte broadcast PERRs (elemid 132 at offset 26, TTL at offset 28)", "fwm.c step_prep_route()/step_perr_forward(): exact injected frame bytes" ], "kernel_refs": [ "sys/netproto/802_11/wlan/ieee80211_hwmp.c:1743", "sys/netproto/802_11/wlan/ieee80211_hwmp.c:1823", "sys/netproto/802_11/wlan/ieee80211_hwmp.c:784", "sys/netproto/802_11/wlan/ieee80211_hwmp.c:1768" ], "poc_changes": "New fwm harness steps 31 (PREP creating route Y via attacker) and 32 (PERR flags=62 seq=0) plus kern.fwm_ttl sysctl; no seed sketch existed.", "attempts": 3, "guest_uname": "DragonFly dfbsd 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": 480, "guest_dirty": 0, "build_cmd": "sh findings/poc/DF-3328/build.sh", "run_cmd": "sh findings/poc/DF-3328/run.sh (steps 31/32 loops, then sysctl kern.fwm_txlog)", "code_hash": "5c225f5fc813a2e5925d1020e5078a829386c450bb53ccb72b70421e942cfbcc", "notes": "1-byte kernel-heap disclosure per forwarded PERR, broadcast over the air; rate ~10/s once a matching route exists. The specific byte (0xff-1) is heap-state-dependent garbage, constant on this kernel/boots - the point is it is provably never sourced from the received frame. Also manifests on the DF-3327-patched kernel (independent path).", "recommended_fix": "Set pperr->perr_ttl = perr->perr_ttl - 1 (inherit from the received frame) and/or allocate pperr with M_ZERO; see fix.diff.", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored (one-line initialization of the propagated TTL, plus M_ZERO suggestion) but not kernel-rebuilt in this run; the change is a trivially side-effect-free initialization of a byte that is currently provably garbage.", "fix_evidence": "findings/poc/DF-3328/fix.diff" } |