{
  "finding_id": "DF-4606",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "ata_timeout() (ata-queue.c:539-562) is a lock-aided callout callback that drops ch->state_mtx mid-execution and re-acquires it at the end, while leaving ch->running set and ch->state == ATA_ACTIVE. Any late ata_interrupt() reaching ata_end_transactions callout_cancel (ata-lowlevel.c:442), or ata_reinit() (ata-all.c:208), or ata_fail_requests() (ata-queue.c:578), all holding state_mtx, then blocks forever: _callout_cancel_or_stop(sync=1) issues LK_CANCEL_BEG and ssleep(\"costp\")s waiting for the callback to return while the callback is blocked re-acquiring the very lock the canceller holds (LKC_CANCEL does not abort a non-CANCELABLE acquisition, kern_lock.c). Deterministic KLD staging of the exact interleaving on the stock guest kernel reproduced the permanent circular wait (sysctl progress probe shows the softclock callback entered the re-acquire lockmgr and never returned; canceller parked on wchan costp; kldunload EBUSY), the loss of the wedged CPUs callwheel (userspace sleep RUN_RC=124), and the death of orderly shutdown (stuck at syncing disks... 0, force-kill required, twice). In-situ ATA trigger additionally needs a >=10 s channel stall then boundary completion, which the emulated PIIX3 cannot produce from inside the guest; window and entry paths proven by source trace. If the callback instead wins the re-acquire race, the same window yields a duplicate completion (second ATA_LF_UNLOCK + second ata_finish). Local DoS from unprivileged IO; no uid=0 route for this class.",
  "exploit_chain": "unprivileged IO -> request armed with callout_init_lk(&request->callout, &ch->state_mtx) -> device stalls >= request->timeout (10 s) -> callout fires ata_timeout which releases state_mtx mid-callback -> late completion interrupt takes state_mtx and calls callout_cancel in ata_end_transaction -> canceller sleeps on costp holding state_mtx; callback blocks re-acquiring state_mtx -> permanent kernel deadlock: boot-disk channel dead + one softclock thread (and its CPUs callwheel) lost -> system wedge (timers and orderly shutdown hang).",
  "evidence": "findings/poc/DF-4606/run.log (progress=3 probe, wchan costp, kldunload EBUSY, RUN_RC=124 sleep, stuck syncing disks... 0); wedge-serial.log (full serial console of run 3 incl. failed shutdown); VERDICT.md (run-by-run narrative incl. run-1 lockmgr_cancel_beg KKASSERT proving the INPROG cancel path); cancelrace.c (deterministic staging of the cited interleaving using the same callout_init_lk/LK_RELEASE/LK_EXCLUSIVE/callout_cancel API sequence)",
  "kernel_refs": [
    "sys/dev/disk/nata/ata-queue.c:557",
    "sys/dev/disk/nata/ata-queue.c:560",
    "sys/dev/disk/nata/ata-queue.c:578",
    "sys/dev/disk/nata/ata-queue.c:93",
    "sys/dev/disk/nata/ata-lowlevel.c:442",
    "sys/dev/disk/nata/ata-all.c:208",
    "sys/dev/disk/nata/ata-all.c:333",
    "sys/kern/kern_timeout.c:609",
    "sys/kern/kern_timeout.c:888",
    "sys/kern/kern_timeout.c:920",
    "sys/kern/kern_lock.c:160"
  ],
  "poc_changes": "Seed sketch did not exist (new finding); authored from scratch. Three harness iterations were needed: (1) canceller originally forgot lockmgr(LK_EXCLUSIVE) before callout_cancel -> exposed the LK_CANCEL_BEG lock must be held KKASSERT instead; (2) callback slept with a timeout inside softclock (illegal: serviced by itself) -> replaced with busy rendezvous; (3) added hw.df4606_progress sysctl probe because kprintf from the post-wedge softclock context does not drain.",
  "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,
  "build_cmd": "cd /tmp/df4606 && make   (KMOD=df4606 SRCS=df4606.c, bsd.kmod.mk against X86_64_GENERIC)",
  "run_cmd": "kldload /tmp/df4606/df4606.ko; sysctl hw.df4606_progress; ps -axH -o state,wchan,comm | grep df4606c",
  "code_hash": "2f068cfdb3c2f7d7b359ed02b808b6ae5da40b4496b9d11a2c88de24d1a1a7b6",
  "notes": "Mechanism-level deterministic reproduction on the stock kernel (the KLD only exercises the public callout/lockmgr API in the same sequence ata uses); in-situ staging impossible on QEMU PIIX3 (no stall dial; 512MB completes in 0.69s). Guest was reset with-src after each wedged run; final state clean.",
  "recommended_fix": "In ata_timeout(), set ch->running = NULL while still holding ch->state_mtx (before LK_RELEASE) -- the comment at ata-queue.c:551-553 already claims this; it closes both the callout_cancel deadlock and the duplicate-completion variant.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored (ch->running = NULL under state_mtx). Not validatable on this guest: baseline requires the in-situ timeout+boundary-completion interleave the emulated hardware cannot stage, and the KLD reproduces the generic primitive, which the ata-queue.c patch cannot affect by construction.",
  "fix_evidence": "findings/poc/DF-4606/fix.diff"
}