DF-3486 / verdict.json
{ "finding_id": "DF-3486", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Deterministic kernel panic on every ng_eiface node creation: panic: try holding ifnet lock in netisr from ifnet_lock() <- if_attach() <- ether_ifattach_bpf() <- ng_eiface_constructor+0xf6 (ng_eiface.c:356). Netgraph control messages run on a TD_TYPE_NETISR thread; if_attach() cannot run there (ifnet lock KASSERT sys/net/if.c:3787 and netmsg_service_sync() at if.c:741 which would self-deadlock \u2014 so on non-INVARIANTS kernels this is a hang rather than a panic). ng_iface carries the same latent calls (ng_iface.c:605 if_attach, ng_iface.c:801 if_detach in ng_iface_rmnode), demonstrated directly once DF-3485 is fixed. Root-only trigger (ng_socket.c:172). This also corrects the DF-3482 lead: the eiface panic is NOT trying to free NULL pointer \u2014 that was inferred from a truncated console window. fix.diff moves the ifnet attach/detach into short-lived kernel threads with a spinlock ownership-transfer state machine; validated: both triggers succeed, ng0/ngeth0 appear in ifconfig, clean shutdown, 22+ rapid create/destroy cycles, zero panics.", "exploit_chain": "", "evidence": "panic.txt (full first-hand stock trace); panic.iface_path.txt (ng_iface variant proving both files affected); fix_run.log (fixed lifecycle: IFACE-CREATED/EIFACE-CREATED, ifconfig ng0/ngeth0, clean shutdown, race stress 0 panics); fix_build.log; unpriv_check.log (EPERM uid 1001)", "kernel_refs": [ "sys/netgraph/eiface/ng_eiface.c:356", "sys/netgraph/iface/ng_iface.c:605", "sys/netgraph/iface/ng_iface.c:801", "sys/net/if_ethersubr.c:622", "sys/net/if.c:689", "sys/net/if.c:741", "sys/net/if.c:3787", "sys/netgraph/socket/ng_socket.c:201", "sys/netgraph/socket/ng_socket.c:172" ], "poc_changes": "none needed \u2014 plain ngctl reproduces on the stock kernel; trigger is 3 lines", "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": 480, "guest_dirty": 0, "build_cmd": "cd /usr/src && patch -p1 < fix.diff && (cd sys/netgraph/eiface && make) && (cd sys/netgraph/iface && make)", "run_cmd": "kldload ng_socket ng_eiface && ngctl mkpeer . eiface e0 ether (root)", "code_hash": "1c8baf8142596f1434d40a3930b0f15c271c34353365fe91bb01f5f16d511690", "notes": "Root-only trigger (verified EPERM as uid 1001). On production (non-INVARIANTS) kernels the observable degrades from clean panic to netmsg_service_sync() self-deadlock. One bug class, two affected modules (ng_eiface.c constructor; ng_iface.c constructor + rmnode) \u2014 filed as one finding since it is one context violation with one fix strategy; DF-3485 is the separate, independent defect that masks this one in stock ng_iface. Residual: ng_eiface_rmnode DONE-path not drivable via ngctl ID addressing (documented in VERDICT.md); fix does not widen pre-existing data/attach race semantics.", "recommended_fix": "Defer the ifnet side of v1 iface/eiface node lifecycle to short-lived kernel threads (spinlock ownership-transfer state machine), never calling if_attach()/if_detach() from the netisr control path \u2014 see fix.diff.", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 (stock kernel; fix applied as module rebuilds only)", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Both fixed modules loaded on the stock kernel: ng_iface and ng_eiface mkpeer triggers that panicked instantly now SUCCEED (ng0/ngeth0 created and visible in ifconfig/ngctl), ngctl shutdown is clean (deferred if_detach thread), and 22+ rapid create/destroy cycles exercising all attach-state transitions produced zero panics with the guest staying up.", "fix_evidence": "fix_run.log; fix_build.log; panic.txt vs fix_run.log (baseline panic -> success)" } |