⬢ DragonFlyBSD Kernel Audit
DF-5486 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5486",
  "status": "reproduced",
  "verdict": "Deterministic kernel panic at USB device plug-in: cue_attach()s usbd_transfer_setup() failure branch (if_cue.c:407-410 allocating USB transfers failed) goto-jumps into the full cue_detach() (if_cue.c:425-426) while the embedded usb_ether is still entirely zeroed (ue_lock/ue_dev/ue_udev/ue_methods/ue_tq are assigned only at if_cue.c:412-416, AFTER the failing call; lockinit of sc_lock at :402 is the only prior softc init). cue_detach() (if_cue.c:436-437) then calls uether_ifdetach(), which lockmgr()s through the NULL ue_lock (Fatal trap 12, fault VA 0x0, Stopped at lockmgr_exclusive+0x5d) - the DF-5334 (if_cdce) class, 8th driver instance: usb_proc_drain() no-ops on the zeroed ue_tq and the ifp!=NULL guard is dead code because uether_getifp() returns the embedded arpcom ifnet. The trigger is fully device-controlled: any evil USB adapter presenting one of the 3 cue_devs[] VID:PID pairs (CATC NETMATE 0x042e:0x5600, NETMATE2 0x042e:0x5601, SmartBridges SMARTLINK 0x087d:0x5600) at config 0/iface 0 without the expected bulk-in/bulk-out endpoints fails the transfer setup. The second failure branch (uether_ifattach error, only on usb_proc_create ENOMEM) additionally runs ether_ifdetach() on a never-if_attach()ed ifnet -> ifindex2ifnet[0] nulling + global ifnet list corruption. Verified with a KLD harness replaying cue_detach() verbatim (its two production calls in order) on the exact branch-1 state, using production usbd_transfer_unsetup()+uether_ifdetach(): baseline on with-src-reset 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) cue_attach detach_usb label doing only unsetup+lockuninit, required for branch 2) both modules rebuilt -Werror clean and the identical harness run SURVIVED with KLDLOAD_RC=0, 0 Fatal traps, clean unload, patched if_cue.ko driver loads/unloads clean (run.log). Softc is zeroed by newbus (subr_bus.c:1953 M_ZERO), so the fault address is fixed 0: not memory corruption with attacker-controlled data. Impact is panic/DoS from physical/VM USB access, same tier as the 7 siblings (Medium).",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "",
  "evidence": "panic.txt (baseline serial: 3 cue_poc markers -> Fatal trap 12, fault virtual address = 0x0, current process 1075 (kldload), Stopped at lockmgr_exclusive+0x5d: orl (%r14),%esi, db> prompt); run.log (patched run: SURVIVED marker from dmesg, KLDLOAD_RC=0, kldstat, UNLOAD_OK, dmesg Fatal-trap count 0 checked twice, patched if_cue.ko loads clean); build.log + fix_uether_build.log + fix_if_cue_build.log (-Werror clean builds); env.txt (guest uname/kldstat/dmesg/compiler); fix.diff (git apply --check OK on clean read-only sys/ tree)",
  "kernel_refs": [
    "sys/bus/u4b/net/if_cue.c:402",
    "sys/bus/u4b/net/if_cue.c:405-410",
    "sys/bus/u4b/net/if_cue.c:412-416",
    "sys/bus/u4b/net/if_cue.c:418-427",
    "sys/bus/u4b/net/if_cue.c:430-441",
    "sys/bus/u4b/net/if_cue.c:436-437",
    "sys/bus/u4b/net/usb_ethernet.c:61",
    "sys/bus/u4b/net/usb_ethernet.c:133-137",
    "sys/bus/u4b/net/usb_ethernet.c:267-305",
    "sys/bus/u4b/usb_process.c:397-410",
    "sys/kern/subr_bus.c:1953"
  ],
  "poc_changes": "No seeded PoC existed. Wrote cue_attach_poc.c from scratch: KLD harness (MODULE_DEPEND uether) that kmallocs a zeroed struct cue_softc, lockinit()s sc->_lock exactly as if_cue.c:402 does (the only softc initialisation before the failing usbd_transfer_setup() at :405), prints the zeroed ue state, then replays cue_detach() verbatim: production usbd_transfer_unsetup(sc->sc_xfer, CUE_N_TRANSFER) (if_cue.c:436) + production uether_ifdetach(&sc->sc_ue) (if_cue.c:437). First build failed (-Werror) because the quoted source line return (0); /* success */ inside the block comment closed it early and one UTF-8 em-dash hit -Werror on exposed code; fixed both, then -Werror clean. Physical CATC Netmate emulation is infeasible in QEMU (no usbredir gadget for this harness class); static cue_attach/cue_detach cannot be linked against, so the branch-1 state + exact call-sequence replay is the strongest runnable evidence and uses only production code after the goto (same evidence class as the 7 sibling findings).",
  "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": 540,
  "guest_dirty": 0,
  "build_cmd": "in-guest: mkdir -p /root/df5486 && cd /root/df5486 && make -m /usr/src/share/mk   (harness; fix validation additionally: cd /usr/src/sys/bus/u4b/net/uether && make; cd ../cue && make; install uether.ko /boot/kernel/)",
  "run_cmd": "in-guest: kldload -v /root/df5486/cue_poc.ko   # baseline: Fatal trap 12 VA 0x0 (stock uether.ko auto-loaded); patched: SURVIVED + RC=0",
  "code_hash": "d67bd13d50df1b75a97513e567b2194da337b1109376f2fc4069f3d1a4e73010",
  "notes": "Pass-2 audit of if_cue.c, pass-1 knowns (DF-1081/DF-2339 cue_setmulti 8-byte hashtbl vs 64-byte 512-bit hash, :311/:329/:338) NOT re-reported. Everything else on the USB-net checklist proven BOUNDED - (a) rx: actlen gate >2+14 at :459, device 16-bit length clamped len=min(actlen-2,len) at :466-467, uether_rxbuf (usb_ethernet.c:589) independently rejects len<ETHER_HDR_LEN or len>MCLBYTES-ETHER_ALIGN and copies into a fresh MCLBYTES cluster, 2+len<=actlen<=bufsize MCLBYTES+2 -> no OOB; single frame per transfer (AOP_RXCOMBINE not set, :615-616) so no multi-frame m_adj accounting exists; (b) tx: pkthdr.len clamped MCLBYTES (:513-514), frame_len len+2<=MCLBYTES+2=bufsize exact fit, usbd_m_copy_in offset 2 (:524), no double-free, error path requeues; (c) register helpers all fixed <=8B buffers, cue_getmac fills ue_eaddr[6] exactly (usb_ethernet.h:107), cue_csr_read_2 uninit-val-on-error only feeds a collisions counter (no secret exposure), PAR0-i loop stays in 0x62-0x67; (e) no m_adj/m_copyback/if_output anywhere in cue; device-fed data limited to the bounded rx length and the 6-byte MAC. Guest: /usr/src verified md5-pristine before baseline (a previous reviewers uether guard had been left in source after their reset; restored from the read-only audit tree; /boot/kernel modules were stock throughout baseline), reset with-src after panic and again after fix validation - returned clean.",
  "recommended_fix": "cue_attach(): route both pre-attach 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 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_cue.ko rebuilt -Werror clean; patched uether.ko installed into /boot/kernel; the IDENTICAL harness re-run: cue_poc: SURVIVED uether_ifdetach() in dmesg, KLDLOAD_RC=0, dmesg|grep -c Fatal trap = 0, kldunload clean, and the patched if_cue.ko driver module loads/unloads clean. Baseline panic record in panic.txt, patched survival in run.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 + patched if_cue.ko load/unload); fix_uether_build.log / fix_if_cue_build.log (-Werror clean); panic.txt (baseline trap on identical input); fix.diff (git apply --check OK on clean tree)"
}