⬢ DragonFlyBSD Kernel Audit
DF-3934 / verdict.json
← back to finding ↓ download raw
{
  "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
}