DF-3934 / verdict.json
{ "finding_id": "DF-3934", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Fix not validated on the guest: the trigger path requires mly/age hardware absent from the audit guest. fix.diff is mechanical (bounds/termination-only) and authored post-verification against the cited lines.", "fix_evidence": "findings/poc/DF-3934/fix.diff + VERDICT.md", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "The age(4) instance of the DF-3761 family (alc): the work-limit knobs are dead code (AGE_PROC_MIN/MAX/DEFAULT defined at if_agevar.h:60-63, referenced nowhere in if_age.c) and age_rxintrs walk for (prog = 0; rr_cons != rr_prod; prog++) (if_age.c:2149) has no prog bound while running under ifp->if_serializer - a line-rate RX flood that keeps the CMB producer ahead of the consumer livelocks the interrupt handler (CPU + NIC starvation; ticks/ioctls starve). Additionally the 16-bit producer/consumer register fields are used unmasked: age_tpd_cons/age_rr_prod (if_age.c:1879-1882, 0..65535) vs rings of 256/512 (if_agevar.h:33-35) - rr_prod >= 512 is an unreachable target for the mod-512 walker, leaving only the nsegs==0 break (:2152-2153) to end the loop, which a hostile ring defeats; and on the TX side an unreachable tpd_cons drains the ENTIRE in-flight ring bounded only by tx_cnt (:1946-1951), freeing mbufs/DMA maps for descriptors the NIC may still own (over-reclaim DMA hazard; index access itself stays wrapped, so no OOB there - the OOB-index variant on the rx side is known DF-1293). Hardware-gated (no L1 NIC in guest); classified inconclusive exactly like family DF-3761.", "exploit_chain": "remote line-rate RX flood (or hostile NIC ring) -> unbounded serializer-held RX walk -> interface/CPU livelock DoS", "evidence": "findings/poc/DF-3934/VERDICT.md (incl. dead-macro grep); fix.diff (AGE_PROC_DEFAULT bound + modulo masks)", "kernel_refs": [ "sys/dev/netif/age/if_age.c:1879", "sys/dev/netif/age/if_age.c:1881", "sys/dev/netif/age/if_age.c:2149", "sys/dev/netif/age/if_age.c:2152", "sys/dev/netif/age/if_age.c:2161", "sys/dev/netif/age/if_age.c:1946", "sys/dev/netif/age/if_agevar.h:60", "sys/dev/netif/age/if_agevar.h:33" ], "poc_changes": "No seed PoC; hardware-gated. Flood trigger needs only an L1 NIC receiving line-rate traffic.", "attempts": 1, "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": 200, "guest_dirty": 0, "notes": "pass-2 GLM5.3. Also noted: age_intrs goto again CMB re-servicing loop (:1878-1925) is the same unbounded-under-serializer family from the hostile-device side.", "recommended_fix": "Bound the age_rxintr walk with AGE_PROC_DEFAULT and mask tpd_cons/rr_prod to their ring sizes.", "build_cmd": null, "run_cmd": null, "code_hash": null } |