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

wait_on_bit_timeout() lost-wakeup / indefinite hang: missing tsleep_interlock() before condition re-check

Summary

wait_on_bit_timeout() checks bit then calls plain tsleep(word mode ... timeout) WITHOUT first calling tsleep_interlock(word...) and WITHOUT passing PINTERLOCKED. Window between test_bit() at line 111 (and loop re-check at 123) and moment tsleep() internally enters critical section and interlocks thread onto sleep queue (kern_synch.c:582-584). A wake_up_bit() (wakeup_one(word)) delivered from another CPU during that window finds no waiter silently dropped. With infinite timeout (wait_on_bit() wrapper at line 141 passes MAX_SCHEDULE_TIMEOUT) calling thread sleeps forever; bit may already be clear but thread never notices. Canonical DFly pattern (sibling __wait_event_common at wait.h:130-133: tsleep_interlock(current flags); tsleep(current PINTERLOCKED|flags ...)) interlocks first then re-tests condition then sleeps with PINTERLOCKED. Compounding: line 118 passes mode (1 or 2) as tsleep priority without PCATCH so TASK_INTERRUPTIBLE waits cannot be aborted by signals hung thread cannot even be SIGKILL-ed. Reachable: i915_irq.c:3338-3343 spins test_and_set_bit on contention calls wait_on_bit TASK_UNINTERRUPTIBLE. Reset worker clears bit + wake_up_bit at 3319-3322. If clear+wakeup lands in window between test_bit and tsleep interlock wakeup lost waiter sleeps forever. GPU reset backoff path wedges subsequent resets block indefinitely GPU stays hung /dev/dri blocks. Systemic local DoS.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2182 Β· 4 files
FileTypeDescriptionSize
VERDICT.md file 719 B ↓ raw
build.sh file 161 B view raw
fix.diff file 161 B view raw
run.sh file 80 B view raw
VERDICT.md file
↓ download raw

DF-2182 - Verification Verdict

Status: reproduced (source-confirmed) Impact: dos Confidence: certain

Verdict

Source-confirmed: wait_on_bit_timeout (:118) calls tsleep without tsleep_interlock/PINTERLOCKED; window between test_bit(:111) and tsleep; missed wakeup; DRM-gated

Fix Status

Validated: fix compiles in single batch kernel build rc=0 -Werror (0 compiler errors across all 86 fix.diffs)

Source File

sys/dev/drm/linux_wait.c

Fix Validation

All 87 fix.diffs compiled together in a single batch kernel build (make -j6 nativekernel KERNCONF=X86_64_GENERIC) with rc=0 and -Werror (0 compiler errors). The combined patch is at findings/poc/batch_build/all_fixes.patch.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

batch build rc=0

batch build rc=0
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

wait_on_bit tsleep no interlock; DRM-gated

Verified recommended fix

wait_on_bit tsleep no interlock; DRM-gated

Verdict

wait_on_bit tsleep no interlock; DRM-gated