DF-3502 / verdict.json
{ "finding_id": "DF-3502", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "ng_fec_delport/ng_fec_rmnode never clear the members ac_netgraph (IFP2NG) while addport stores the node pointer there, and rmnode clears the shared ng_ether_input_p global unconditionally. After any fec teardown the member keeps a dangling node pointer; the next fec node creation re-arms the global, and the next inbound ethernet frame on that member runs ng_fec_input over freed memory: reproduced deterministically as a page fault at address 0x3f8 (priv==NULL, offsetof(fec_bundle)=0x3f8) in RX/interrupt context (Idle process), with the freed node chunk provably reused by an echo node at the identical address. Secondary facet: rmnodes unconditional clear blinds every other live fec bundle and ng_ether(4), which shares the same global. Fixed and validated: with delport clearing IFP2NG and the global clear made reference-counted, the identical detonation sequence survives (3/3 pings, no panic).", "exploit_chain": "create fec node -> add_iface <ether member> (IFP2NG= node) -> shutdown node (member left with dangling IFP2NG; shared global cleared) -> create any new fec node (global re-armed) -> first inbound frame on the member: ng_fec_input dereferences freed node -> NULL+0x3f8 read -> kernel panic", "evidence": "panic.txt (Fatal trap 12, fault VA 0x3f8, Stopped at ng_fec_input+0x30, current process Idle); run.log (step-by-step with node addresses 0xfffff80117ab2840 freed then reused by echo node at the same address); run.sh; fixes.sh + fix.diff", "kernel_refs": [ "sys/netgraph/fec/ng_fec.c:379", "sys/netgraph/fec/ng_fec.c:464", "sys/netgraph/fec/ng_fec.c:752", "sys/netgraph/fec/ng_fec.c:1133", "sys/netgraph/fec/ng_fec.c:1233", "sys/net/if_ethersubr.c:1273" ], "poc_changes": "driven from thread context via fecdrive.ko (stock csock path blocked by DF-3499/DF-3500); lab enablers E1/E2/E3 documented in enablers.sh \u2014 none touch the defect", "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": 1800, "guest_dirty": 0, "build_cmd": "sh enablers.sh && sh fixes.sh # HEAD source + E1-E3 + fix in /usr/src/sys/netgraph/fec", "run_cmd": "sh run.sh # create + add vtnet0, then detached: shutdown; echo; create; ifconfig vtnet0 up; ping 10.0.2.2", "code_hash": "e8cf25ff47210caf1634a98849d42b0c3a21526ed2c514447dbbe92969d59bae", "notes": "State creation needs the netgraph control socket (root on stock DFly, e.g. admin teardown of a bundle); detonation needs no privilege (any inbound frame after the member is next upped). Grooming angle documented: reuse of the freed node chunk by a node with a live private makes ng_fec_input walk a foreign bundle list instead of faulting.", "recommended_fix": "delport: clear ac->ac_netgraph when it equals priv->node; rmnode: clear ng_ether_input_p only when the last fec node is destroyed and the global still points at ng_fec_input", "fix_status": "fixed", "fix_notes": "fix.diff applied in-guest and validated: identical sequence (shutdown -> echo chunk reuse -> create -> ifconfig up -> ping) completes with no panic, 3/3 pings, guest healthy" } |