⬢ DragonFlyBSD Kernel Audit
DF-4753 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4753",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Structural defect certain by source trace: the cxm(4) driver has no lock anywhere (struct cxm_softc cxm.h:216-264; zero lockmgr/priv_check in cxm.c). Every exported cxm_msp_* function (cxm_msp34xxx.c) dereferences sc/sc->iicbus/sc->dev, and the unprivileged ioctl path BT848_SAUDIO (0444 cdev, cxm.c:1885; no open-mode gate, no priv_check) reaches cxm_msp_wait_for_lock which tsleeps ~0.5 s (cxm_msp34xxx.c:601-622) with sc referenced only from the sleeping threads stack. Privileged kldunload cxm then runs cxm_detach (cxm.c:1944-2004): dev_ops_remove_minor only dead-vectors NEW calls (kern_conf.c:334-343); the in-flight sleeper resumes into freed softc - cxm_msp_is_locked reads sc->iicbus (cxm_msp34xxx.c:560) and device_printf(sc->dev) (cxm_msp34xxx.c:624) dereference freed memory -> NULL/garbage device_t vtable dispatch -> panic (memcorrupt family; cxm twin of bktr DF-4419, Low because the freeing half is privileged). Folded sibling of the same no-locking family: cxm_opens unlocked is_opened TOCTOU (cxm.c:2158-2161). Runtime reproduction hardware-gated: kldload cxm succeeds on the guest but no Conexant iTVC15/16 PCI card exists, so /dev/cxm0 never appears (run.log) and the victim ioctl cannot be instantiated; fix.diff compile-validated as the full cxm.ko module with -Werror (fix_build.log rc=0).",
  "exploit_chain": "unprivileged: open /dev/cxmN O_RDONLY (0444) -> ioctl(BT848_SAUDIO, AUDIO_TUNER) parks in cxm_msp_wait_for_lock tsleep (~0.5 s window, repeatable); privileged: kldunload cxm frees the softc mid-sleep; on wake: UAF read of sc->iicbus + method dispatch on dangling device_t + device_printf(sc->dev) deref -> panic. Heap-reclaim code-exec ceiling exists in theory (controlled reallocation of the freed softc before wake) but was not developed: hardware-gated.",
  "evidence": "VERDICT.md (line-by-line trace + negative results for the DF-1600 twin and msp_name overflow); run.log (kldload cxm OK, /dev/cxm* absent, kldunload OK); build.log vs fix_build.log (baseline and patched cxm.ko both rc=0, -Werror); fix.diff; cxm_uaf_race.c (verified ioctl constants from ioctl_bt848.h:83,130)",
  "kernel_refs": [
    "sys/dev/video/cxm/cxm_msp34xxx.c:295",
    "sys/dev/video/cxm/cxm_msp34xxx.c:588-626",
    "sys/dev/video/cxm/cxm_msp34xxx.c:624",
    "sys/dev/video/cxm/cxm.c:1885",
    "sys/dev/video/cxm/cxm.c:1944-2004",
    "sys/dev/video/cxm/cxm.c:2158-2161"
  ],
  "poc_changes": "Authored fresh (no seed): BT848_SAUDIO _IOW(x,46,int) / AUDIO_TUNER 0x00 confirmed from sys/dev/video/bktr/ioctl_bt848.h; program exits 3 with explicit hardware-gated message when /dev/cxmN is absent.",
  "attempts": 3,
  "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": 660,
  "guest_dirty": 0,
  "build_cmd": "cd /root/cxmbuild_fix/cxm && make   (KMOD= cxm, bsd.kmod.mk, -Werror)",
  "run_cmd": "sh run.sh  (victim half; killer half: while :; do kldunload cxm; kldload cxm; done as root)",
  "code_hash": "719406d7e697d1cece38a8db250b61910c1805f23b48069312f30b23db436de1",
  "notes": "Hunt items killed as negative results: DF-1600 carrier-detect loop does NOT exist in cxm_msp34xxx.c (AUTOMATIC standard select + 2-byte register polling instead); msp_name uses bounded ksnprintf into [10] (bktr DF-1850 pattern does not carry over); read/write helpers have no short-read uninit use; no volume table and no division exist in this file. cxm_read remains unlocked - owned by DF-3941s rework, noted in fix residual. Guest /usr/src restored to pristine (sha256 verified).",
  "recommended_fix": "Add a softc lock serializing cdev entry points against cxm_detach (drain before teardown); see fix.diff.",
  "fix_status": "inconclusive",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (cxm.h lock member + lockinit + open/close/ioctl serialization via cxm_ioctl wrapper + detach drain + lockuninit) compiles clean as the full cxm.ko module (-Werror, rc=0) on guest 6.5-DEVELOPMENT source. Behavioral validation requires cxm hardware absent from this guest; baseline bad behavior therefore also unobservable here.",
  "fix_evidence": "fix_build.log (patched module, rc=0); build.log (baseline module, rc=0); fix.diff"
}