{
  "finding_id": "DF-4066",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none observed (hardware-gated); source-level: kernel OOB write (8-byte NULL store up to +512KB past chain array) + wild-pointer mbuf writes + type confusion into ether_input via NIC-DMAd uint16_t descriptor index",
  "confidence": "certain",
  "verdict": "Source-level certain, runtime hardware-gated (inconclusive per family convention, matching DF-3604/DF-3989/DF-4024/DF-4045/DF-4055). ti_rxeof takes the receive source-ring index from the NIC-DMAd return-ring descriptor field ti_idx (uint16_t, if_tireg.h:707/711) at if_ti.c:1638 and uses it raw to index the mbuf chain arrays -- three times, with no bounds check: jumbo path if_ti.c:1648-1649 (array TI_JUMBO_RX_RING_CNT=256), mini path if_ti.c:1662-1663 (TI_MINI_RX_RING_CNT=1024), std path if_ti.c:1676-1677 (TI_STD_RX_RING_CNT=512). An out-of-range index (any value >= array size, up to 65535) yields: (1) an OOB kernel WRITE -- chain[rxidx] = NULL stores 8 zero bytes at base+8*rxidx, landing in adjacent chain arrays, ti_jslots[] (corrupting ti_sc/ti_buf used by ti_jfree/ti_jref, if_ti.c:643-681), or up to +511,760 bytes past the array outside struct ti_softc; (2) an OOB kernel READ whose result is used as struct mbuf *m: if_ti.c:1690 then stores m->m_pkthdr.len = m->m_len = cur_rx->ti_len (two stores through the wild pointer, value NIC-chosen) and if_ti.c:1706 feeds m to ifp->if_input -> ether_input/BPF (wild-mbuf type confusion); NULL/garbage reads give an immediate panic (DoS floor), groomed values (e.g. ti_jslots kernel pointers) give a controlled-corruption ceiling. The driver itself only writes in-bounds r->ti_idx (if_ti.c:714/750/812), so well-behaved firmware never trips this -- the kernel simply must not trust the DMAd field (same boundary as the DF-3604 family). Runtime: the audit guest has zero Tigon-family PCI devices (env.txt: vendors 0x12ae/0x10b7/0x1385/0x10a9/0x1011 absent, virtio-net only; if_ti.ko present but unattachable), so the fault path cannot be exercised; trigger.c (geometry model) builds and runs on the guest (run.log RC=0) proving the index-to-offset math. This is the index variant of the bce/ale/re/stge/et length-trust family and is strictly stronger: it adds an OOB write primitive.",
  "exploit_chain": "On real (faulty/malicious) Tigon/Tigon2 hardware or via PCIe DMA tampering: return-ring descriptor with TI_BDFLAG_JUMBO_RING and chosen 16-bit ti_idx=k>=256 -> (1) 8-byte NULL write at ti_rx_jumbo_chain+8k (softc-relative, attacker-chosen granularity); (2) OOB read of the same address becomes m; (3) two attacker-valued stores at m+8/m_pkthdr.len offsets (if_ti.c:1690); (4) wild-mbuf walk through ether_input/BPF (if_ti.c:1706) -> leak or panic. Minimum guaranteed impact: NULL-deref panic (DoS); ceiling: softc-relative NULL-store corruption + type-confused mbuf traversal.",
  "evidence": "run.log (per-path geometry table: which region each DMAd rxidx NULL-writes / OOB-reads, RC=0); build.log; env.txt (no Tigon PCI devices on guest, md5 match of audited source); VERDICT.md (full path:line trace + cleared-classes negative notes); trigger.c; fix.diff; fix_build.log (patched module compiles -Werror clean on guest)",
  "kernel_refs": [
    "sys/dev/netif/ti/if_ti.c:1636",
    "sys/dev/netif/ti/if_ti.c:1638",
    "sys/dev/netif/ti/if_ti.c:1648",
    "sys/dev/netif/ti/if_ti.c:1649",
    "sys/dev/netif/ti/if_ti.c:1662",
    "sys/dev/netif/ti/if_ti.c:1663",
    "sys/dev/netif/ti/if_ti.c:1676",
    "sys/dev/netif/ti/if_ti.c:1677",
    "sys/dev/netif/ti/if_ti.c:1690",
    "sys/dev/netif/ti/if_ti.c:1706",
    "sys/dev/netif/ti/if_ti.c:714",
    "sys/dev/netif/ti/if_ti.c:750",
    "sys/dev/netif/ti/if_ti.c:812",
    "sys/dev/netif/ti/if_tireg.h:707",
    "sys/dev/netif/ti/if_tireg.h:711",
    "sys/dev/netif/ti/if_tireg.h:397",
    "sys/dev/netif/ti/if_tireg.h:399",
    "sys/dev/netif/ti/if_tireg.h:1099",
    "sys/dev/netif/ti/if_tireg.h:1102"
  ],
  "poc_changes": "No seed PoC (no prior findings on this file). Authored trigger.c as a softc-geometry model per the DF-4024 convention; fixed an initial region-labeling off-by-array in the model (offsets now computed from struct base, not indexed-array base); honest hardware-absent verification.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 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": 55,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -Wextra -o /tmp/df4066 /tmp/df4066.c",
  "run_cmd": "vm.sh run_root /tmp/df4066; echo RC=$?",
  "code_hash": "d6e8956b97ea5bd02455fbfc3632434f9717793e8f12725a0cfb6856e8c3fc36",
  "notes": "Pass-2 checklist item (b)/(a) cross-hit for if_ti.c. Guest hygiene: /usr/src restored to pristine md5 75c1662ad472e7c0d19e6964a1078ec2 after fix-build checks; only /tmp artifacts left. Cleared this pass: firmware download paths (compile-time arrays, static sizes, if_ti.c:402-454); EEPROM reads caller-bounded; ti_mem window walk in-bounds; cmd-ring indices masked; TX ring walks masked (Tigon-1 banked window mapping correct, if_ti.c:1733-1748); jumbo pool locking consistent.",
  "recommended_fix": "Bounds-check rxidx against TI_JUMBO_RX_RING_CNT / TI_MINI_RX_RING_CNT / TI_STD_RX_RING_CNT on the three receive paths in ti_rxeof (ierror + drop), see fix.diff.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff adds per-path rxidx bounds checks using the drivers own drop idiom; git apply --check passes against the read-only sys/ tree and the patched if_ti.ko builds clean on the guest with -Werror -std=gnu11 (fix_build.log FIXBUILD_f1_RC=0); runtime validation impossible without Tigon hardware.",
  "fix_evidence": "findings/poc/DF-4066/fix.diff + findings/poc/DF-4066/fix_build.log"
}