DF-4112 / verdict.json
{ "finding_id": "DF-4112", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Mechanism PROVEN on the guest kernel by deterministic replica of if_nge.cs exact callout/serializer protocol; nge-specific runtime hardware-gated (inconclusive per family convention, as DF-3715). nge_tick (sys/dev/netif/nge/if_nge.c:1366-1406) is the callback of a plain-callout_init (if_nge.c:731) 1 Hz timer (if_nge.c:1717) that BLOCKS in lwkt_serialize_enter (if_nge.c:1372) and re-arms itself inside the serializer (if_nge.c:1403); nge_stop() (if_nge.c:2094) tears it down with callout_stop() while the caller holds that same serializer (nge_ioctl :2031, nge_init :1716, nge_watchdog :2067, nge_detach :934, and nge_intr :1491 in the interrupt thread). DragonFly callout_stop synchronously waits for an in-progress callback (kern_timeout.c:1091 -> ssleep costp at :920), so a parked callback deadlocks against the stopper (AB-BA): both threads wedge permanently, the interface serializer is never released, the affected CPUs softclock thread stops delivering all callouts, and (observed) the sysctl subsystem blocks. Kernel-module replica on the guest: stop under a held serializer with the nge-shaped handler parked -> callout_stop NEVER returned (thread D5 wchan costp); fix-shape control (lwkt_serialize_try + 1-tick retry, the proposed fix) is fully unloaded by callout_stop under the serializer on this kernel (pending=0, firing stalled) - fix mechanism validated. Post-wedge guests cannot be shut down cleanly.", "exploit_chain": "", "evidence": "findings/poc/DF-4112/run.log (decisive lines: handler PARKED on our serializer (fired=8 ran=7) - entering callout_stop() then marker then silence; ps 989 D5 costp; fix-shape callout_stop RETURNED ... pending=0 fired-stalled=YES); build.log (BUILD_RC=0); VERDICT.md; fix.diff (try-enter + 1-tick retry)", "kernel_refs": [ "sys/dev/netif/nge/if_nge.c:731", "sys/dev/netif/nge/if_nge.c:1372", "sys/dev/netif/nge/if_nge.c:1403", "sys/dev/netif/nge/if_nge.c:1717", "sys/dev/netif/nge/if_nge.c:2094", "sys/dev/netif/nge/if_nge.c:2031", "sys/dev/netif/nge/if_nge.c:1716", "sys/dev/netif/nge/if_nge.c:2067", "sys/dev/netif/nge/if_nge.c:934", "sys/dev/netif/nge/if_nge.c:1491", "sys/kern/kern_timeout.c:920", "sys/kern/kern_timeout.c:1091", "sys/kern/lwkt_serialize.c:234" ], "poc_changes": "No seed PoC. Authored tlnge_replica.ko (out-of-tree module) replicating the exact nge protocol because the guest has no DP83820 hardware.", "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": 600, "guest_dirty": 0, "build_cmd": "cd /root/kmod && make", "run_cmd": "vm.sh run_root kldload /root/kmod/tlnge_replica.ko; sysctl kern.ngereplica.arm=1; sleep 3; (sysctl kern.ngereplica.stop_blk=1 >/dev/null 2>&1 &); sleep 6; dmesg | grep replica; ps -o pid,stat,wchan,command -ax | grep stop_blk", "code_hash": "594a6097b8dcfeb807d4daacceaf175455f5d9df544f188a0509f177a486d7d1", "notes": "Trigger on nge hardware: ifconfig nge0 down/up, SIOCSIFMTU, kldunload if_nge, watchdog reinit, or any interrupt while the interface is admin-down (nge_intr -> nge_stop directly, if_nge.c:1490-1493). Family parent: DF-3715 (em(4)).", "recommended_fix": "Make nge_tick() non-blocking: lwkt_serialize_try() with a 1-tick callout_reset retry.", "fix_status": "not_tested", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff (try-enter + 1-tick retry) authored against the read-only sys/ tree, patch --dry-run clean. Fix MECHANISM validated on this kernel by the modules fix-shape control (callout_stop under a held serializer returns and fully unloads the try-based handler: pending=0, firing stalled). The patched nge driver itself cannot be exercised without DP83820 hardware.", "fix_evidence": "findings/poc/DF-4112/fix.diff; findings/poc/DF-4112/run.log fix-shape section" } |