{
  "finding_id": "DF-3418",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Reproduced on the stock INVARIANTS 6-cpu guest: rtpurelookup() in in6_ifdetach_dispatch() (sys/netinet6/in6_ifattach.c:844) takes a reference (sys/net/route.c:276) that is only dropped inside the `rt->rt_ifp == ifp` branch (in6_ifattach.c:845-849). When the ff02::1%ifp lookup instead matches a foreign route (the installed IPv6 default route), the reference is leaked permanently; deleting that route afterwards leaves its rtentry+sockaddrs allocated forever. Measured with vmstat -m routetbl: 10x route add/delete alone = +0 objects; 10x tap create/destroy alone = +0 objects; 10x combined = +18 objects; 20x combined = +38 objects (~1.9 objects/cycle, stable across two runs). Unbounded repetition = unbounded kernel memory retention from routine interface detach + route churn (root-triggered; Low).",
  "exploit_chain": "",
  "evidence": [
    "findings/poc/DF-3418/run.log — decisive vmstat -m routetbl counts: control runs flat (258->258, 276->276), test runs grow (258->276, 278->316)",
    "findings/poc/DF-3418/README.md — root cause, reproduce steps, observed table, fix",
    "sys/netinet6/in6_ifattach.c:844-849 — lookup ref never dropped on the rt_ifp != ifp path",
    "sys/net/route.c:276 — _rtlookup() increments rt_refcnt on every successful match",
    "sys/netinet/in.c:1462-1464 — the IPv4 twin in_ifdetach loops udbinfo; no analogous leak there because its route purge uses different code paths"
  ],
  "kernel_refs": [
    "sys/netinet6/in6_ifattach.c:844",
    "sys/netinet6/in6_ifattach.c:845-849",
    "sys/net/route.c:276",
    "sys/net/route.c:286-293"
  ],
  "poc_changes": "No seed PoC existed; authored from scratch: pure shell orchestration (route add/delete + ifconfig tap create/destroy) with vmstat -m routetbl as the observable, three-way A/B/C attribution.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC\tx86_64",
  "runtime_sec": 180,
  "guest_dirty": 0,
  "build_cmd": "(no compile; shell-only PoC)",
  "run_cmd": "sh findings/poc/DF-3418/run.sh  (as root on the guest; see run.log for the exact executed commands)",
  "code_hash": "",
  "notes": "Leak is permanent per interface-detach-with-foreign-route event; materializes as memory retention when the pinned route is later deleted (DHCPv6/PPP default-route churn). Low severity: requires root to trigger detach/route ops; impact is slow unbounded kernel memory growth. DF-3417 pack (UDP6 purge-gap candidate) kept on disk as the honest false-positive record: udp6_attach hardcodes udbinfo[0] (udp6_usrreq.c) so udbinfo[0]-only purge is currently complete for UDP6.",
  "recommended_fix": "Drop the rtpurelookup() reference on all non-NULL paths (rtfree(rt) when rt->rt_ifp != ifp); see fix.diff",
  "fix_status": "not_testable",
  "fix_kernel_uname": "",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored against the read-only sys/ tree (reference dropped on the foreign-route path via rtfree); kernel rebuild validation not performed in this run (leak-class finding; mechanical fix). The leak is fully explained by the missing rtfree and the measured growth disappears by construction once the reference is dropped.",
  "fix_evidence": "findings/poc/DF-3418/fix.diff"
}
