⬢ DragonFlyBSD Kernel Audit
DF-4192 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4192",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "REPRODUCED: an unprivileged local user races concurrent SNDCTL_DSP_SETTRIGGER START/STOP ioctls on a shared 0666 /dev/dsp descriptor; chn_trigger() (sys/dev/sound/pcm/channel.c:2190-2225) flips c->trigger under CHN_LOCK but performs the channels.pcm.busy insert/remove after dropping CHN_LOCK under PCM_LOCK, so the two halves interleave: (a) STOP-before-insert makes CHN_REMOVE/SLIST_REMOVE walk past the list end -> NULL->sle_next deref at struct offset 0x138 -> Fatal trap 12 kernel panic (captured: fault VA 0x138, RIP chn_trigger+0x263, process=unprivileged trighammer); (b) interleaved insert/remove builds a cyclic list -> the same walk spins forever in kernel mode holding the channel lock -> silent unrecoverable whole-system hang (captured via DDB: spin at chn_trigger+0x26a/+0x263 plus all dsp/mixer clients blocked in lockmgr_exclusive). Verified live on QEMU ES1370 (kldload snd_es137x); the defect is in the pcm core sound.ko, reachable through any pcm driver, es137x being the audited vehicle. Availability-only: no uid=0 chain exists (wild access is a fixed-offset read from NULL; list writes stay inside valid nodes).",
  "exploit_chain": "",
  "evidence": "panic.txt (full Fatal trap 12 ... 0x138 ... chn_trigger+0x263 with current process = PoC pid 953); run.log (baseline wedge runs + DDB samples); ddb_ps_stuck_threads.txt + ddb_blocked_stacks.txt (dsp_open/mixer_ioctl/dsp_ioctl threads blocked behind the spinning lock holder); VERDICT.md (complete narrative incl. disassembly of the spin loop d230-d23d from guest sound.ko); fix_build.log (patched module md5 0d076339...); env.txt (0666 nodes, unpriv attacker).",
  "kernel_refs": [
    "sys/dev/sound/pcm/channel.c:2198",
    "sys/dev/sound/pcm/channel.c:2201",
    "sys/dev/sound/pcm/channel.c:2215",
    "sys/dev/sound/pcm/channel.c:2218",
    "sys/dev/sound/pcm/channel.h:190",
    "sys/dev/sound/pcm/channel.h:193",
    "sys/dev/sound/pcm/channel.h:213"
  ],
  "poc_changes": "n/a - PoC written from scratch for this finding (trighammer.c); es_batt.c is the wider discovery battery.",
  "attempts": 4,
  "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  x86_64",
  "runtime_sec": 5400,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -pthread -o /tmp/trighammer /tmp/trighammer.c",
  "run_cmd": "/tmp/trighammer 30",
  "code_hash": "6f057be38134ad1cbfd29fd939dd72928d3289ab457e4c45b042d116e704e489",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff swaps CHN_INSERT_HEAD/CHN_REMOVE for the CHN_INSERT_HEAD_SAFE/CHN_REMOVE_SAFE macros (already present in channel.h:193-221, previously unused) at channel.c:2201/2218. Patched sound.ko (md5 0d076339abf53061007aa1deeecedfd7) built on the guest from /usr/src/sys and installed to /boot/kernel. Exact PoC re-run on the patched module: NO panic and NO system-wide wedge across >10 minutes of hammering (3x60s + 30s trighammer plus battery attempts; zero Fatal trap on serial; DDB samples idle) - the previously-observed bad behavior is GONE (fix_patched_reproduced=0 denotes the BUG did not reproduce). Residual, noted honestly: the PoC process itself can still end up permanently blocked in a dsp ioctl because the flag/list desync itself persists (_SAFE only prevents the memory fault and the cycle); a complete fix should make the trigger transition atomic with respect to the busy-list bookkeeping.",
  "fix_evidence": "fix.diff; fix_build.log (build transcript, module md5s, installed-symbol check); VERDICT.md FIX VALIDATION section.",
  "notes": "Discovered during the pass-2 audit of sys/dev/sound/pci/es137x.c via live QEMU ES1370 testing; defect lives in the pcm core (sound.ko) and is driver-independent. Guest handed back clean (vm.sh revert with-src + vm.sh up, stock kernel, no audio device).",
  "recommended_fix": "Use the existing CHN_INSERT_HEAD_SAFE/CHN_REMOVE_SAFE macros in chn_trigger() (channel.c:2201,2218); longer term, make the c->trigger transition atomic with the channels.pcm.busy list bookkeeping."
}