DF-3669 / verdict.json
{ "finding_id": "DF-3669", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "Source-level certain defect, runtime-untestable: ix_txgc_timer (if_ix.c:352-374) re-arms itself every tick (373); ix_stop only callout_stop()s it (1767), which cannot stop an in-flight callback from re-arming; ix_detach terminates sc->timer and sc->fw_timer (693,696) but never the per-ring tx_gc_timer, then frees tx_base/tx_buf/maps (721 -> 2090-2123) and kfrees tx_rings (4002). The orphaned 1-tick callout then fires on freed memory: UAF read of if_flags, UAF write via lwkt_serialize_try on the freed serializer, and callout-queue corruption via callout_reset on the freed embedded callout. Trigger is root-only (kldunload/hot-remove of an attached ixgbe NIC) with a per-tick race window -> Low severity. Guest has no ixgbe device (env.txt), so no runtime reproduction; fix.diff (callout_terminate per ring at detach) compile-validated with -Werror on md5-identical guest source.", "exploit_chain": "", "evidence": "VERDICT.md (full path:line race walk); build_patched.log; env.txt", "kernel_refs": [ "sys/dev/netif/ix/if_ix.c:352", "sys/dev/netif/ix/if_ix.c:373", "sys/dev/netif/ix/if_ix.c:1767", "sys/dev/netif/ix/if_ix.c:693", "sys/dev/netif/ix/if_ix.c:721", "sys/dev/netif/ix/if_ix.c:4002", "sys/dev/netif/ix/if_ix.c:2090" ], "poc_changes": "New pass-2 finding, no seed.", "attempts": 1, "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": 60, "guest_dirty": 0, "build_cmd": "cd /usr/src && patch -p1 < fix.diff && cd sys/dev/netif/ix && make obj && make", "run_cmd": "n/a (needs attached ixgbe NIC + root-initiated detach race)", "code_hash": "8ad35fc6d20327cb30c893c949242669ae62a12f57cec74d280f1080da7bd989", "notes": "confidence likely on exploitability of the race (window analysis), certain on the missing-terminate defect itself.", "recommended_fix": "callout_terminate() every tx_gc_timer in ix_detach() before ix_free_rings() (fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Compile-validated only; runtime race validation needs an attached NIC.", "fix_evidence": "build_baseline.log / build_patched.log (-Werror clean with fix)." } |