{
  "finding_id": "DF-3546",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "v1 ng_bpf accepts cyclic ifMatch/ifNotMatch configs (incl. ifMatch==thisHook) and the v1 core forwards synchronously with no hop bound (ng_send_data calls the peer rcvdata directly), so one injected packet recurses until the kernel stack guard page double-faults. Verified live on the stock INVARIANTS guest in both self and cross cycle modes: DOUBLE FAULT - KERNEL STACK GUARD HIT! / panic: double fault, rip inside ng_bpf.ko. Root-only trigger (v1 ngc_attach caps_priv_check; uid 1001 gets errno 43), so privileged DoS like the ng7 twin DF-3540.",
  "exploit_chain": "",
  "evidence": "panic.txt (double fault signature, rip=0xffffffff82656970 inside ng_bpf.ko), console_self.txt + console_cross_tail.txt (fresh boot then panic for each mode), run.self.log (program output stops at injection; ssh died with guest), unpriv_check.txt (uid 1001 EPROTONOSUPPORT), fix1_self.log + fix2_cross.log (patched module: EINVAL guard / ELOOP depth-drop, guest survives)",
  "kernel_refs": [
    "sys/netgraph/bpf/ng_bpf.c:419",
    "sys/netgraph/bpf/ng_bpf.c:431",
    "sys/netgraph/bpf/ng_bpf.c:474",
    "sys/netgraph/netgraph/ng_base.c:1678",
    "sys/netgraph/netgraph/ng_base.c:1685",
    "sys/netgraph/socket/ng_socket.c:172"
  ],
  "poc_changes": "Adapted the ng7 DF-3540 trigger to the v1 user ABI: NG_VERSION 2 header layout (arglen u16 at offset 2, flags/token/typecookie/cmd order), NGM_GENERIC_COOKIE 851672668, synchronous control delivery (errors via errno, no NODEINFO round-trip needed), named socket node for the data-socket connect. Fixed one trigger bug found during verification: NGM_CONNECT con.path must be relative to the addressed node (p), not socket-relative (in.p) -- first cross attempt failed ENOENT.",
  "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": 2700,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o /root/ng_cycle_v1 /root/ng_cycle_v1.c   (in-guest, root; cc 8.3 [DragonFly])",
  "run_cmd": "kldload netgraph ng_socket ng_bpf; /root/ng_cycle_v1 self  (then reset with-src; /root/ng_cycle_v1 cross)",
  "code_hash": "f31b0e82e730865da7117a3b38f8a873cf33176bd79cd568d481498a7f3b9f0a",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applied to guest /usr/src only; ng_bpf.ko rebuilt -Werror-clean and loaded. Stock: self=panic, cross=panic. Patched: self -> SET_PROGRAM EINVAL (thisHook guard), cross -> sendto ELOOP at depth 16, guest survives 30s in both. fix.diff never applied to the audit sys/ tree.",
  "fix_evidence": "fix1_self.log (errno=22 EINVAL on x1->x1), fix2_cross.log (errno=62 ELOOP, RESULT no-panic survived 30s), fix_build.log (-Werror module build)",
  "notes": "v1 twin of DF-3540 (ng7): different failure mode -- v1 has no items/tokens/hop accounting at all, the recursion exhausts the kstack (guard-page double fault) instead of tripping the LWKT token-array KKASSERT. Verified DF-3444s unvalidated-filter primitive does NOT apply to v1: ng_bpf_setprog calls bpf_validate (ng_bpf.c:481) and this trees bpf_validate bounds BPF_MEM/ST/STX and rejects len<1/len>BPF_MAXINSNS (sys/net/bpf_filter.c:511-517).",
  "recommended_fix": "ng_bpf_setprog: reject ifMatch/ifNotMatch == thisHook (non-empty); bound recursive forwarding depth in ng_bpf_rcvdata (ELOOP past 16 hops) -- or better, add a hop bound to v1 ng_send_data itself."
}