{
  "finding_id": "DF-3551",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Reproduced live on the stock v1 netgraph stack: every packet pushed into sample:debug leaks exactly one mbuf, permanently and linearly (+300, +1200, +500 across three runs; netstat -m in run.log), while the drained-downstream control run leaks zero. Root cause: ng_xxx_newhook gives the debug hook private==NULL (sys/netgraph/ng_sample.c:238-242) while the downstream hook always has private set (:237), so the only free in ng_xxx_rcvdataqs else-branch, if (hook == xxxp->downstream_hook.hook) NG_FREE_DATA(m, meta) (:390-394), is unreachable dead code and the function returns 0 with the caller-owned mbuf+meta still allocated (v1 rcvdata contract at :314-317 requires the receiver to free). v1 twin of DF-0690 (ng7, which was only source-confirmed/inconclusive), here demonstrated live. Realistic ceiling is kernel mbuf-pool exhaustion (system-wide networking DoS), but the module does not ship and node creation is root-gated (caps_priv_check, sys/netgraph/socket/ng_socket.c:172) - severity Low.",
  "exploit_chain": "Resource exhaustion only: root loads ng_sample.ko and instantiates a sample node (or any existing sample:debug hook is fed by a peer) -> sustained sends into sample:debug grow the kernel mbuf count without bound -> mb_map exhaustion -> networking DoS. No memory-safety primitive (never-freed, not use-after-free).",
  "evidence": "run.log (netstat -m deltas: control +0, debug +300/+1200/+500 exactly; leaked mbufs persist across runs), v1demo.c (leakdbg/leakctl modes), fix.diff (unconditional NG_FREE_DATA in the debug-only else branch)",
  "kernel_refs": [
    "sys/netgraph/ng_sample.c:237",
    "sys/netgraph/ng_sample.c:238",
    "sys/netgraph/ng_sample.c:314",
    "sys/netgraph/ng_sample.c:390",
    "sys/netgraph/ng_sample.c:393"
  ],
  "poc_changes": "Same v1demo.c driver as DF-3550 (leakdbg/leakctl modes); initial run mistakenly sent to the sample-side hook name instead of the local socket hook - fixed by tracking the our-side hook (sd/dbg) separately.",
  "attempts": 3,
  "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": 1800,
  "guest_dirty": 0,
  "build_cmd": "make -C /root/ngs1 KMOD=ng_sample; cc -O2 -Wall -o /root/v1demo /root/v1demo.c (same as DF-3550)",
  "run_cmd": "kldload ng_socket; kldload /root/ngs1/ng_sample.ko; netstat -m; /root/v1demo leakctl 1200; netstat -m; /root/v1demo leakdbg 300; netstat -m; /root/v1demo leakdbg 1200; netstat -m",
  "code_hash": "1517851c923420332e62c40c89ead87fbaeb6967e76d529de564364011b5e929",
  "fix_status": "not_tested",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Two-line fix (drop the dead downstream comparison, free unconditionally in the provably debug-only else branch, fix.diff, git-apply --check clean); kernel rebuild validation skipped per contract (Low severity, not memory corruption).",
  "fix_evidence": "fix.diff",
  "notes": "The ng7 twin DF-0690 was only source-confirmed (inconclusive); this v1 verification closes the loop for the v1 half of the template pair.",
  "recommended_fix": "Replace the unreachable conditional free at ng_sample.c:390-394 with an unconditional NG_FREE_DATA(m, meta)."
}