tsleep while holding queue_lock deadlocks interrupt handler permanently hanging IPS controller
Summary
ips_ioctl_cmd acquires sc->queue_lock LK_EXCLUSIVE at ips_ioctl.c:125 issues hardware command via ips_ioctl_start (132) then enters tsleep() polling loop (133-134) WITHOUT releasing lock. DragonFlyBSD tsleep does NOT release lockmgr locks only lksleep does (kern_synch.c:831-843). Command-completion interrupt handler (ips_morpheus_intr ips.c:585 or ips_copperhead_intr ips.c:769) must acquire same queue_lock to process result update ioctl_cmd->status.value. Lock permanently held by sleeping ioctl thread interrupt handler blocks forever status never updated tsleep loop never exits. Permanently hangs calling thread blocks ALL I/O on IPS RAID controller no interrupts ever processed. If root/boot filesystem on IPS logical drive entire system hangs requires hard reset. Attacker: root or operator group via /dev/ipsN (0600 root:operator ips.c:452-454) issues ioctl(fd IPS_USER_CMD &req). ioctl hangs permanently. queue_lock held forever interrupt ithread permanently blocked every disk I/O targeting any IPS logical drive hangs. Timeout watchdog (ips_timeout ips.c:331) also needs queue_lock (ips.c:337) blocked no self-healing. Contrast: internal command path ips_commands.c correctly uses ips_timed_wait() (no lock during wait) and ips_wakeup_callback() (proper wakeup). Also ips_ioctl_finish never calls wakeup(ioctl_cmd) so even without lock issue would poll at 100ms. Attack trivially reliable every IPS_USER_CMD triggers deadlock unconditionally on hardware.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2163 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-level analysis with path:line citations | 1.9 KB | β raw |
| reachability.txt | environment | guest PCI/device survey proving no required HW | 1.6 KB | view raw |
| fix.diff | suggested-fix | git-apply-able fix (validated: applies clean) | 431 B | view raw |
| build.sh | build-log | documents HW requirement | 550 B | view raw |
| run.sh | run-log | documents HW requirement | 272 B | view raw |
| env.txt | environment | guest uname and environment | 491 B | view raw |
DF-2163: tsleep while holding queue_lock deadlocks IPS interrupt handler
Verdict: NOT REPRODUCED (HW-gated) β source-confirmed real bug
Reachability
NOT reachable on this QEMU guest. ips_ioctl_cmd() is in sys/dev/raid/ips/ips_ioctl.c,
part of the ips(4) IBM ServeRAID driver. device ips is in GENERIC but requires IBM
ServeRAID PCI hardware. PCI survey: no ServeRAID controller. ls /dev/ips* β not present.
The ioctl path (IPS_USER_CMD) is only reachable via an attached ips device node.
Mechanism (source-confirmed)
ips_ioctl_cmd() at ips_ioctl.c:125-139:
1. Line 125: lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY) β acquires exclusive lock
2. Line 132: ips_ioctl_start(command) β submits hardware command
3. Lines 133-134: while (ioctl_cmd->status.value == 0xffffffff) tsleep(ioctl_cmd, 0, "ips", hz/10)
β sleeps while holding queue_lock
4. Line 139: lockmgr(&sc->queue_lock, LK_RELEASE) β releases lock after command completes
The bug: DragonFlyBSD's tsleep() does NOT release lockmgr locks β only lksleep()
does (see kern_synch.c:831-843). The IPS interrupt handler (ips_intr) needs
queue_lock to signal command completion (set ioctl_cmd->status.value), but it can't
acquire the lock because ips_ioctl_cmd() holds it while sleeping.
Result: permanent deadlock. The ioctl never returns, the controller is hung, and any
further IPS I/O is blocked. This is a local DoS (requires ips device access, typically
root or operator group).
Primitive
- Class: deadlock / permanent DoS
- Impact: hangs the IPS controller indefinitely
- Requires access to the ips device (typically root-only)
Fix
fix.diff: Replace tsleep() with lksleep() at line 134:
lksleep(ioctl_cmd, &sc->queue_lock, 0, "ips", hz / 10);
lksleep() releases queue_lock during sleep and re-acquires it on wakeup, allowing the
interrupt handler to complete the command.
Fix verification
not_testablegit apply --check clean
git apply --check clean
Confirmed kernel references
β
Detail
Exploit chain
none (HW-gated)
Evidence (decisive lines)
HW-GATED (no IBM ServeRAID). Source-confirmed: ips_ioctl_cmd holds LK_EXCLUSIVE then tsleep without lksleep -> permanent deadlock.
Verified recommended fix
HW-GATED (no IBM ServeRAID). Source-confirmed: ips_ioctl_cmd holds LK_EXCLUSIVE then tsleep without lksleep -> permanent deadlock.
Verdict
HW-GATED (no IBM ServeRAID). Source-confirmed: ips_ioctl_cmd holds LK_EXCLUSIVE then tsleep without lksleep -> permanent deadlock.
No comments yet.