DF-5514 / verdict.json
{ "finding_id": "DF-5514", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "Deterministic kernel panic at USB device plug-in: ipheth_attach()s four error branches (if_ipheth.c:235 Cannot set alternate setting, :241 Cannot setup USB transfers, :252 Cannot get MAC address, :258 could not attach interface) all goto-jump into the full ipheth_detach() (if_ipheth.c:262-263 -> :267-281) while the embedded usb_ether was never attached via uether_ifattach(). On branches 1-2 the ue_sc/ue_dev/ue_udev/ue_lock/ue_methods assignments at :243-247 have not run yet (softc is newbus M_ZERO, subr_bus.c:1953), so uether_ifdetach() (usb_ethernet.c:267-305) lockmgr()s through the NULL ue_lock \u2014 Fatal trap 12, fault VA 0x0, Stopped at lockmgr_exclusive+0x5d \u2014 after usb_proc_drain() no-ops on the zeroed ue_tq and the ifp!=NULL guard proves dead (uether_getifp() returns the embedded arpcom ifnet, usb_ethernet.c:133-137). On branches 3-4 (ue_lock valid, uether_ifattach never ran / self-freed its ue_tq via usb_proc_creates error path) the same call instead reaches ether_ifdetach() on the never-if_attach()ed embedded ifnet \u2014 the DF-2341/DF-5493 latent corruption path. The trigger is fully device-controlled: ipheth_devs[] is a product-agnostic match (:174-177), so any evil USB adapter with vendor 0x05ac exposing interface class 0xff/subclass 0xfd/protocol 1 that STALLs SET_INTERFACE(alt 1), omits the bulk endpoints, or STALLs the 0x40 GET_MACADDR vendor request panics the host at plug-in \u2014 9th and last driver instance of the DF-5334 class (cdce/aue/axge/urndis/mos/udav/kue/cue). Verified with a KLD harness replaying ipheth_detach() verbatim (its two production calls in order) on the exact branch-1 state, using production usbd_transfer_unsetup()+uether_ifdetach(): baseline on the fresh with-src guest with stock uether.ko -> Fatal trap 12 VA 0x0, guest dead in DDB (panic.txt); with fix.diff ((a) uether_ifdetach early-return on NULL ue_lock + (b) ipheth_attach detach_usb label doing only unsetup+lockuninit, required for branches 3-4) both modules rebuilt -Werror clean and the byte-identical harness (md5 f27308481209578091ab79c853df1979) SURVIVED with KLDLOAD_RC=0, 0 Fatal traps, clean unload; patched if_ipheth.ko loads/unloads clean (run.log, fix_smoke.log). Fault address is fixed 0 (NULL lock pointer): panic/DoS from physical/VM USB access, no attacker-controlled data is written, no privesc path \u2014 same tier as the 8 siblings (Medium).", "exploit_chain": "", "evidence": "panic.txt (baseline serial: 3 ipheth_poc markers -> Fatal user address access from kernel mode from kldload, Fatal trap 12, fault virtual address = 0x0, Stopped at lockmgr_exclusive+0x5d: orl (%r14),%esi, db> prompt, vm.sh status=down); run.log (patched run: SURVIVED marker in dmesg, KLDLOAD_RC=0, kldstat, UNLOAD_OK, Fatal-trap count 0, identical .ko md5 f27308481209578091ab79c853df1979); build.log (-Werror clean harness build); fix_build.log (uether.ko + if_ipheth.ko rebuilt -Werror clean after fix.diff); fix_smoke.log (patched if_ipheth.ko load/unload clean); env.txt (guest uname/kldstat/dmesg); fix.diff (git apply --check OK on clean read-only sys/ tree)", "kernel_refs": [ "sys/bus/u4b/net/if_ipheth.c:217-265", "sys/bus/u4b/net/if_ipheth.c:225-229", "sys/bus/u4b/net/if_ipheth.c:231-236", "sys/bus/u4b/net/if_ipheth.c:237-247", "sys/bus/u4b/net/if_ipheth.c:249-259", "sys/bus/u4b/net/if_ipheth.c:262-264", "sys/bus/u4b/net/if_ipheth.c:267-281", "sys/bus/u4b/net/if_ipheth.c:274", "sys/bus/u4b/net/if_ipheth.c:276", "sys/bus/u4b/net/if_ipheth.c:174-177", "sys/bus/u4b/net/usb_ethernet.c:133-137", "sys/bus/u4b/net/usb_ethernet.c:162-189", "sys/bus/u4b/net/usb_ethernet.c:267-305", "sys/bus/u4b/net/usb_ethernet.c:549-560", "sys/bus/u4b/net/usb_ethernet.h:80-84", "sys/bus/u4b/usb_process.c:397-410", "sys/kern/subr_bus.c:1953" ], "poc_changes": "No seeded PoC existed. Wrote ipheth_poc.c from scratch on the DF-5486 sibling harness template: KLD module (MODULE_DEPEND uether) that kmallocs a zeroed struct ipheth_softc, replicates the only pre-failure softc init exactly (sc_iface_no=0 per :225, lockinit(&sc->sc_lock,...) per :229), prints the zeroed ue state, then replays ipheth_detach() verbatim: production usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER) (:274) + production uether_ifdetach(&sc->sc_ue) (:276). Built -Werror clean on the first attempt. Physical Apple-device emulation is infeasible in QEMU (no iPhone USB gadget; ipheth_attach/ipheth_detach are static); the branch-1 state + exact production call-sequence replay is the strongest runnable evidence and uses only production code after the goto (same evidence class as the 8 sibling packs).", "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\t x86_64", "runtime_sec": 1500, "guest_dirty": 0, "build_cmd": "in-guest: mkdir -p /root/df5514 && cd /root/df5514 && make -m /usr/src/share/mk (harness; fix validation additionally: cd /usr/src/sys/bus/u4b/net/uether && make; cd ../ipheth && make; install uether.ko /boot/kernel/)", "run_cmd": "in-guest: kldload -v /root/df5514/ipheth_poc.ko # baseline: Fatal trap 12 VA 0x0 (stock uether.ko auto-loaded); patched: SURVIVED + RC=0", "code_hash": "10e4da721f425f31d1a3c579aea28741dc8bd9023d24c01820e784d955d0c6ae", "notes": "Pass-2 audit of if_ipheth.c (pass 1 recorded no findings \u2014 DB-verified). Single actionable finding; this completes the DF-5334 family sweep of sys/bus/u4b/net (9 driver instances + core owner DF-5493). Everything else on the USB-net checklist proven BOUNDED \u2014 (a) rx: uether_newbuf() itself m_adj(ETHER_ALIGN)s the MCLBYTES cluster (usb_ethernet.c:549-560), ipheth adds a second ETHER_ALIGN adj (:511, matches FreeBSD verbatim), HC-programmed DMA <=2044 into [cl+4,cl+2048), TRANSFERRED len = usbd_xfer_frame_len() is host-controller-clamped actual length (NOT a device-parsed field like urndis rm_datalen), len<16 gate frees, m_adj(2) then uether_rxmbuf(len-2 <= 2042) == exact remaining cluster capacity -> no DF-5396-class overflow; frames=1 so no multi-frame accounting; no DF-5400 actlen-vs-pktlen confusion; (b) tx: pkthdr.len clamped to 1516 (:422-423), usbd_m_copy_in into 1516-byte frame slot at x*1516<=10612<12128, usbd_frame_zero in-slot, error path frees sc_tx_buf before tr_setup re-entry, CANCELLED frees -> no OOB/double-free/leak; VLAN frames >1516 silently truncated (inherited Linux/FreeBSD ipheth semantics, functional only); (c) helpers exact fit: GET_MACADDR wLength=6 -> sc_data[64] -> ue_eaddr[6]; tick wLength=64 == sizeof(sc_data); sc_carrier_on (:328-329) is never read anywhere \u2014 carrier check is dead code, short control responses would leave stale sc_data[0] but the value is never consumed (Info, not filed); (d) attach/detach \u2014 THE finding above; branch-3/4 ether_ifdetach-on-unattached mechanism is core-owned (DF-2341/DF-5493); usb_proc_create failure self-frees ue_tq so the minimal detach_usb label is correct for all 4 branches; (e) device-supplied data limited to the 6-byte MAC (spoofable like any USB NIC), the dead carrier byte, and the HC-bounded rx length \u2014 no RNDIS-style parsed headers in this driver, nothing feeds m_adj/m_copyback/if_output unbounded. Guest reset with-src after the panic and again after fix validation \u2014 returned clean.", "recommended_fix": "ipheth_attach(): route all four pre-uether_ifattach() failures to a detach_usb label doing only usbd_transfer_unsetup()+lockuninit(); uether_ifdetach(): early-return when ue->ue_lock==NULL (class-wide, same guard as DF-5334/5384/5486 fix)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applied in-guest to /usr/src (patch(1) Plan A, both files, all hunks); uether.ko and if_ipheth.ko rebuilt -Werror clean; patched uether.ko installed into /boot/kernel; the byte-identical harness re-run (md5 f27308481209578091ab79c853df1979): ipheth_poc: SURVIVED uether_ifdetach() in dmesg, KLDLOAD_RC=0, dmesg|grep -c Fatal trap = 0, kldunload clean, and the patched if_ipheth.ko driver module loads/unloads clean. Baseline panic record in panic.txt, patched survival in run.log + fix_smoke.log. fix.diff verified git-apply-able against the clean read-only sys/ tree (git apply --check OK).", "fix_evidence": "run.log (SURVIVED marker + KLDLOAD_RC=0 + kldstat + UNLOAD_OK + Fatal-trap count 0 + identical md5); fix_build.log (both modules -Werror clean); fix_smoke.log (patched if_ipheth.ko load/unload clean); panic.txt (baseline trap on identical input); fix.diff (git apply --check OK on clean tree)" } |