{
 "finding_id": "DF-3367",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "dos",
 "confidence": "certain",
 "verdict": "RTM_CHANGE whose new gateway equals the routes own destination takes rt_setgates EADDRNOTAVAIL path (route.c:1193-1205), which deletes the route from the current CPUs tree, while rtsearch_msghandlers temporary reference (route.c:1726-1729) is dropped to zero without a finalizing rtfree: the rtentry, its key chunk and its ifa reference leak permanently on that CPU, and the per-CPU routing tables diverge (CPUs 1..N keep the route). Verified empirically as root with plain route(8): 200 add+change cycles grew the routetbl malloc type from 1.48K/257K to 3.82K/669K in-use allocations with zero routes visible on cpu0, and `route delete -host 10.99.2.1` (a route cpu0 does not have) succeeded via the surviving CPU1..N copies. A subsequent RTM_ADD of the same destination deterministically panics via route.c:763-768 (cpu0 adds, cpu1 EEXIST) \u2014 traced, deliberately not triggered during verification. Privileged trigger only (routing socket write), hence Low severity: robustness/lifetime bug, memory-exhaustion and panic DoS by root or a compromised routing daemon.",
 "exploit_chain": "root (or compromised routing daemon): route add -host A GW; route change -host A A -> leaked rtentry+ifa on cpu0, table divergence; re-adding A later panics the kernel (rtrequest1_msghandler route.c:763-768). No unprivileged trigger exists (route_output requires privilege for RTM_CHANGE, rtsock.c:738-740).",
 "evidence": [
  "findings/poc/DF-3367/leakcheck2.log \u2014 vmstat -m routetbl BEFORE 1.48K/257K -> AFTER-200-CYCLES 3.82K/669K; routes visible on cpu0: 0; `route delete -host 10.99.2.1` returns rc=0 (route exists only on cpus 1..N = divergence proven)",
  "findings/poc/DF-3367/leakcheck.log \u2014 first 100-cycle confirmation",
  "findings/poc/DF-3367/README.md \u2014 full refcount trace route.c:1726-1729 + 1193-1205"
 ],
 "kernel_refs": [
  "sys/net/route.c:1193-1205",
  "sys/net/route.c:1726-1729",
  "sys/net/route.c:813-868",
  "sys/net/route.c:763-768",
  "sys/net/rtsock.c:928-936"
 ],
 "poc_changes": "no C PoC needed \u2014 plain route(8) add/change cycles reproduce; measurement via vmstat -m (M_RTABLE = routetbl)",
 "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": 95,
 "guest_dirty": 0,
 "build_cmd": "(none; route(8))",
 "run_cmd": "for i in 1..200: route add -host 10.99.2.$i 10.0.2.15 && route change -host 10.99.2.$i 10.99.2.$i ; vmstat -m | grep routetbl",
 "code_hash": "",
 "notes": "panic leg (re-ADD after divergence -> rtrequest1_msghandler panic route.c:763-768) traced but not triggered to avoid aborting the concurrent DF-3366 fix-validation kernel build. Cleanup: leftover phantom 10.99.2.x routes on cpus 1..N removed; guest reset planned before returning.",
 "recommended_fix": "Make rtsearch_msghandler drop its temp ref with RTFREE()-style finalization (route.c:1729), or stop rt_setgates EADDRNOTAVAIL path from mutating the tree and fail the outer RTM_CHANGE atomically on all CPUs."
}