⬢ DragonFlyBSD Kernel Audit
DF-3601 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3601",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Deterministic kernel self-deadlock: writing dev.hdaa.N.reconfig=1 (root-only, the documented audio reconfiguration interface) never returns and freezes the whole system. The sysctl handler mutates the newbus device tree (device_delete_children/bus_generic_attach) from inside sysctl-handler context where userland_sysctl() holds the per-CPU global sysctllock SHARED, while pcm child (un)registration takes _sysctl_xlock() = every CPUs gd_sysctllock EXCLUSIVE \u2014 the thread waits for its own shared hold forever and poisons sysctl system-wide. Reproduced 2/2 on QEMU intel-hda+hda-duplex (benign codec \u2014 hardware-independent). Fixed by deferring the reconfiguration to a taskqueue; fix validated on-guest (trigger returns rc=0, pcm0 detaches/re-attaches, system healthy, second reconfig clean).",
  "exploit_chain": "root: sysctl dev.hdaa.0.reconfig=1 -> hdaa_sysctl_reconfig (hdaa.c:6474) -> device_delete_children (hdaa.c:6492) -> hdaa_pcm_detach -> pcm_unregister -> sysctl_ctx_free (sound.c:1233) -> sysctl_unregister_oid -> SYSCTL_XLOCK (kern_sysctl.c:171) -> _sysctl_xlock takes every CPUs gd_sysctllock EXCLUSIVE (kern_sysctl.c:1642) while the same thread holds its own CPUs lock SHARED (kern_sysctl.c:1572) -> permanent sleep; wedge spreads system-wide.",
  "evidence": "run.log (write syscall never returns; t+120s even new ssh hangs; qemu alive, no panic); boot.log.firstwedge / boot.log.repro2 (console silent after attach); fix_validation.log (patched module: RC=0, pcm0: detached then re-attach, HEALTH_OK, 2 consecutive reconfigs); fix.diff (taskqueue deferral, patch -p1 zero fuzz).",
  "kernel_refs": [
    "sys/dev/sound/pci/hda/hdaa.c:6474",
    "sys/dev/sound/pci/hda/hdaa.c:6492",
    "sys/dev/sound/pci/hda/hdaa.c:6498",
    "sys/kern/kern_sysctl.c:1572",
    "sys/kern/kern_sysctl.c:1642",
    "sys/kern/kern_sysctl.c:171",
    "sys/dev/sound/pcm/sound.c:1233"
  ],
  "poc_changes": "No code PoC needed beyond `sysctl dev.hdaa.0.reconfig=1`; guest needed booting with -device intel-hda -device hda-duplex (vm.sh temporarily extended via HDA_ARGS env var, reverted after).",
  "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": 1500,
  "guest_dirty": 0,
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Deferred-taskqueue fix (hdaa.c: sysctl handler enqueues reconfig_task; hdaa.h: struct task member; attach TASK_INIT; detach taskqueue_drain) built as a module (-Werror clean) and swapped into the guest: the previously-hanging sysctl now returns rc=0 in <1s, dmesg shows pcm0 detach/re-attach cycle, /dev/dsp0 recreated, two consecutive reconfigs and full sysctl/ssh health verified.",
  "fix_evidence": "findings/poc/DF-3601/fix_validation.log; findings/poc/DF-3601/fix.diff",
  "build_cmd": "cd /usr/src/sys/dev/sound/driver/hda && make",
  "run_cmd": "kldload snd_hda && sysctl dev.hdaa.0.reconfig=1",
  "code_hash": "",
  "notes": "Trigger requires root (SYSCAP_NOSYSCTL_WR gate, kern_sysctl.c:1447) \u2014 privilege-gated kernel freeze, hence dos severity Medium not High. Guest HDA args reverted and guest reset to with-src snapshot after validation. attempts=3: two baseline reproductions (both wedged) + one patched validation run.",
  "recommended_fix": "Defer device_delete_children/unconfigure/configure/bus_generic_attach out of the sysctl handler into a taskqueue (hdaa_reconfig_task on taskqueue_thread[mycpuid]); drain it in hdaa_detach."
}