⬢ DragonFlyBSD Kernel Audit
DF-3387 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-3387",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "dos",
 "confidence": "certain",
 "verdict": "Reproduced 2/2 on the stock INVARIANTS guest: lagg_input() (sys/net/lagg/if_lagg.c:1466-1470) frees the mbuf and NULLs it under IFF_MONITOR, then falls through to ether_reinput_oncpu(scifp, NULL, REINPUT_RUNBPF); with the lagg master IFF_UP, ether_reinput_oncpu (sys/net/if_ethersubr.c:1317-1320) writes ifp to m->m_pkthdr.rcvif of a NULL mbuf -> Fatal trap 12 at vaddr 0xa0, Stopped at ether_reinput_oncpu+0x1a: movq %rdi,0xa0(%rsi). Trigger is a single frame received on any slave (write(2) to /dev/tapN = RX injection via tapwrite -> if_input); setup is privileged ifconfig. Write-only fault at fixed near-NULL address: clean DoS panic, no controllable primitive, no escalation path.",
 "exploit_chain": "ifconfig tap0 create/up; ifconfig lagg0 create; ifconfig lagg0 laggproto failover; ifconfig lagg0 laggport tap0 (slave if_type becomes IFT_IEEE8023ADLAG -> RX diverted to lagg_input at if_ethersubr.c:1076 before L3); ifconfig lagg0 up monitor; write 34 bytes (bcast ether + minimal IPv4) to /dev/tap0 -> deterministic panic on the first received packet. Remote variant: once configured, any frame arriving on any slave (e.g. ambient broadcast) panics the kernel.",
 "evidence": [
  "panic.txt / panic.2.txt: Fatal trap 12 ... fault virtual address = 0xa0 ... Stopped at ether_reinput_oncpu+0x1a: movq %rdi,0xa0(%rsi)",
  "run.2.log: all 7 ifconfig steps rc=0, connection dropped immediately after (write() executed, output lost to the panic)",
  "panic.2.txt serial mirror: [df3387] + ifconfig lagg0 up monitor -> rc=0 directly followed by the panic",
  "fix.diff: two hunks (if_lagg.c return-after-monitor-discard; if_ethersubr.c defensive NULL guard)",
  "run.patched.log + build.log: patched kernel #1, same PoC -> NO PANIC - bug did not reproduce, guest stays up"
 ],
 "kernel_refs": [
  "sys/net/lagg/if_lagg.c:1462",
  "sys/net/lagg/if_lagg.c:1466",
  "sys/net/lagg/if_lagg.c:1470",
  "sys/net/lagg/if_lagg.c:674",
  "sys/net/if_ethersubr.c:1303",
  "sys/net/if_ethersubr.c:1317",
  "sys/net/if_ethersubr.c:1320",
  "sys/net/if_ethersubr.c:1076"
 ],
 "poc_changes": "Seed (none existed for this bug; written fresh). Frame content beyond the 14-byte header is irrelevant since the IFT_IEEE8023ADLAG branch in ether_demux_oncpu runs before any L3 processing; a 34-byte bcast/ETHERTYPE_IP frame is used for realism. Progress lines mirrored to /dev/console because the panic eats unflushed ssh output.",
 "attempts": 2,
 "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": 138,
 "guest_dirty": 0,
 "build_cmd": "cc -O -g -Wall -o /root/df3387_trigger /root/df3387/trigger.c",
 "run_cmd": "/root/df3387_trigger",
 "code_hash": "a63e094858d0c393561618c44320dc57c06a76931718573bd0e3679505d8a2e9",
 "notes": "Same profile as DF-0445 (privileged config + traffic-triggered panic, Medium). Distinct from DF-0367 (unlocked ifp->if_lagg deref, lines 1442-1456). Other ether_reinput_oncpu callers (vlan/carp/bridge) never pass NULL; lagg is the outlier violating the if_ethersubr.c contract. Guest reset to clean-source snapshot after validation.",
 "recommended_fix": "if_lagg.c: return immediately after the IFF_MONITOR discard (do not reinput a consumed mbuf); if_ethersubr.c: defensive NULL check at top of ether_reinput_oncpu.",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Fri Sep 11 23:54:18 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "fix.diff applied in-guest to /usr/src, make -j8 nativekernel KERNCONF=X86_64_GENERIC + make installkernel, rebooted into #1. Exact PoC re-run: frame harmlessly discarded by the monitor path, NO PANIC - bug did not reproduce printed, lagg0/tap0 destroyed cleanly, guest remained up and ssh-able. Baseline panicked 2/2 on the same input.",
 "fix_evidence": "run.patched.log (full PoC output on patched kernel), build.log (kernel build tail + uname)"
}