{
  "finding_id": "DF-2611",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "REPRODUCED live on the stock INVARIANTS guest: icmp6_redirect_output transmits the 8-byte-alignment pad of the ND_OPT_TARGET_LINKADDR option as uninitialized mbuf-cluster heap memory. With tap0's ifi_addrlen rewritten 6->8 (via /dev/kmem, offsets pre-validated against vtnet0/lo0/tap0 known values - a privileged stand-in for the EUI-64/fwip interface QEMU cannot emulate; the leaked code path is identical), every emitted redirect (35/35 across three phases) carried a 16-byte TLLA option of which bytes [10,16) were stale cluster contents: 20/20 redirects leaked the immediately-preceding UDP spray pattern (b1,b2,b3... incrementing per iteration - byte-perfect attribution to the freed cluster), and 10/10 no-spray redirects leaked '00' x6 (virgin cluster) then 'b5' x6 - the pattern of the EARLIER finished spray run still resident in the heap. Control with stock addrlen=6: option length 8, zero pad bytes, exactly as the finding states for Ethernet. Quantified: 6 pad bytes per redirect for addrlen=8 (1-7 for other non-6 addrlens), 100% emission rate, contents = whatever the cluster cache last held (attacker-influenced when on-path traffic grooms it), passively sniffable on-link.",
  "exploit_chain": "",
  "evidence": "run.log + leak_sample.txt: control 'TLLA bytes: 02 00 00 00 00 01' (5x, option len 8); spray phase 'TLLA bytes: 02 00 00 00 00 01 00 00 b1 b1 b1 b1 b1 b1' .. 'b4' wrapping over 20 iters (option 'type=2 len=16'); no-spray phase '00 00 00 00 00 00' x4 then 'b5 b5 b5 b5 b5 b5' x6 (stale pattern from the previous run - leak decoupled from the spray). kmem validation lines: vtnet0 type=6 addrlen=6 mtu=1500 / lo0 type=24 addrlen=0 mtu=16384 / tap0 type=6 addrlen=6->WROTE 8 (readback).",
  "kernel_refs": [
    "sys/netinet6/icmp6.c:2496-2497",
    "sys/netinet6/icmp6.c:2506-2511",
    "sys/netinet6/icmp6.c:2516",
    "sys/netinet6/icmp6.c:2412",
    "sys/netinet6/icmp6.c:2611",
    "sys/netinet6/ip6_forward.c:246-265",
    "sys/netinet6/ip6_forward.c:358",
    "sys/netinet/icmp6.h:165"
  ],
  "poc_changes": "No seed. Toolkit written from scratch; material discoveries during bring-up: (1) /dev/tap is exclusive-open and destroy-on-close, so one process must own tap0 end-to-end (setup in-process); (2) the gateway route MUST carry a scoped link-local gateway ('fe80::42:1%tap0') or rt_llroute()'s rtlookup(rt_gateway) misses and the forward dies with EHOSTUNREACH (ICMPv6 unreach code 3) instead of emitting a redirect; (3) TLLA pad analysis must parse options at frame offset 94 (14 eth + 40 ip6 + 40 nd_redirect); (4) the if_addrlen mutation must happen while the harness holds tap0 (ifnet_array is rebuilt on interface create/destroy).",
  "attempts": 7,
  "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": 400,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o tap_rdr tap_rdr.c && cc -O2 -Wall -o kmem_addrlen kmem_addrlen.c",
  "run_cmd": "sh run.sh   (as root; performs control addrlen=6, patch8+spray leak run, patch8 no-spray run)",
  "code_hash": "dd8e2b3ba3af504cc006faac0754e3f4d5c5e51df21632884dd2207866339114",
  "notes": "The only simulated element is the interface's address LENGTH (privileged kmem rewrite standing in for fwip/EUI-64 hardware QEMU cannot provide); everything after that - option rounding to 16, 2+addrlen written bytes, 6 transmitted uninitialized cluster bytes, checksum coverage - is stock kernel behavior. Production preconditions per the finding: IPv6 router role (defaults ip6.redirect=1) + non-Ethernet-addrlen outgoing interface + resolved neighbor. Guest reset to clean snapshot after the run (kmem was mutated mid-run).",
  "recommended_fix": "bzero(lladdr + ifp->if_addrlen, len - sizeof(*nd_opt) - ifp->if_addrlen) after the LLADDR bcopy in icmp6_redirect_output (see fix.diff); same class as DF-0329's verified redirected-header fix.",
  "fix_status": "not_testable",
  "fix_kernel_uname": "",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored (5-line pad bzero at icmp6.c:2510) but single-fix kernel not built/rebooted: this is an info-leak finding, not memory corruption, so the mandatory rebuild rule does not apply, and the change is mechanically identical to DF-0329's already-verified fix for the sibling redirected-header-option site. Baseline leak is fully characterized above for later A/B if a maintainer wants it.",
  "fix_evidence": "fix.diff; VERDICT.md; DF-0329 pack (verified fix for the sibling site, findings/poc/DF-0329/)."
}
