β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2163

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2163 Β· 6 files
FileTypeDescriptionSize
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
VERDICT.md verdict source-level analysis with path:line citations
↓ download 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_testable
baseline no→ patch + rebuild →patched clean

git 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.