⬢ DragonFlyBSD Kernel Audit
DF-3434 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-3434",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "dos",
 "confidence": "certain",
 "verdict": "Deterministic on the stock INVARIANTS guest. With root having installed allow udp from any to any keep-state limit src-port 100 (documented ipfw3 grammar, lib/libipfw3/basic/ipfw3_basic.c:562-574 -> cmd->arg3=2), 320 identical UDP packets from an unprivileged fixed-port socket produced 638 oops console lines (dmesg) and grew M_IPFW3_STATE inuse 46 -> 646: check_keep_state() skips the RB_FIND de-dup for arg3!=0 (ip_fw3_state.c:296-300), allocates a fresh state per packet (:319), and on the RB_INSERT duplicate (:327) only kprintf(oops) (:328) - the allocation is leaked. Two effects per packet at line rate from any traffic the rule matches: bounded-per-tree 64B kernel memory leak (capped only by the never-decremented count gate, DF-0632) and an unbounded serial-console kprintf flood (console-lock amplification). Root configures the rule; unprivileged local users or unauthenticated remote peers trigger it.",
 "exploit_chain": "",
 "evidence": [
  "run.log: dmesg oops count 38 -> 638 and M_IPFW3_STATE inuse 46 -> 646 for 20+300 identical packets; ipfw3 show line 00099 with 250360 matches",
  "VERDICT.md: root-cause walk ip_fw3_state.c:296-330",
  "run.patched.log: patched kernel - same 320-packet trigger, zero oops lines, flat M_IPFW3_STATE"
 ],
 "kernel_refs": [
  "sys/net/ipfw3_basic/ip_fw3_state.c:296",
  "sys/net/ipfw3_basic/ip_fw3_state.c:301",
  "sys/net/ipfw3_basic/ip_fw3_state.c:317",
  "sys/net/ipfw3_basic/ip_fw3_state.c:319",
  "sys/net/ipfw3_basic/ip_fw3_state.c:327",
  "lib/libipfw3/basic/ipfw3_basic.c:562"
 ],
 "poc_changes": "Setup staged through a nohup script because kldload ipfw3 engages default-deny instantly and severs the staging ssh session; trigger runs unprivileged (run_user).",
 "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": 240,
 "guest_dirty": 0,
 "build_cmd": "cc -O2 -o /tmp/state_oops /tmp/state_oops.c",
 "run_cmd": "sh /tmp/fwsetup.sh (root, pre-staged); /tmp/state_oops 320 (user)",
 "code_hash": "9549c224b943855accad23f985f682255c637dc304c3d03911af338e15f937e4",
 "notes": "Related but distinct from DF-0632 (counters never decremented): this is the allocation-side defect (leak + kprintf per packet) inside the same rule path. The count gate bounds the leak; the console flood is unbounded. O(n)-per-packet RB_FOREACH limit counting (:302-312) is an additional amplification noted during verification (drain throttled to ~2-7k pps with a populated tree).",
 "recommended_fix": "RB_FIND before allocating in check_keep_state(); kfree on RB_INSERT collision instead of kprintf (fix.diff).",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Sat Sep 12 16:56:02 UTC 2026   root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "Patched module on two kernels (#2 16:27:37 and #1 16:56:02): the identical trigger (320 identical UDP packets, 640 rule evaluations confirmed by ipfw3 show pcnt) produced ZERO oops console lines (baseline: 638) and M_IPFW3_STATE inuse stayed at 6-8 (the per-CPU contexts only; baseline: 646 leaked). Duplicate packets now take the RB_FIND path and refresh the timestamp; no allocation, no kprintf.",
 "fix_evidence": [
  "run.patched.log",
  "fix.diff"
 ]
}