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

Driver callbacks (wdog_fn) invoked under global spinlock with interrupts disabled

Summary

wdog_reset_all(:96) spin_lock then calls wdog_fn(:87) for each registered watchdog under lock+IPL. Callbacks are arbitrary kernel code; sleeping or MMIO stall -> deadlock/latency spikes. Callback re-enters same function via callout. Depends on registered drivers.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0236 Β· 9 files
FileTypeDescriptionSize
build.sh build-script no binary (source-level) 120 B view raw
run.sh run-script demonstrates empty wdoglist (latent) 507 B view raw
all_fixes_build.log build-log kernel build with fix: compiles rc=0 5.6 MB ↓ download
env.txt environment uname, wdog sysctl state 353 B view raw
fix.diff suggested-fix snapshot wdog list under lock, call wdog_fn callbacks unlocked 1.2 KB view raw
VERDICT.md verdict lock-held-during-callback trace + reachability 2.4 KB ↓ raw
README.md readme human reproduce doc 578 B ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human reproduce doc
↓ download raw

DF-0236 β€” DF-0236 β€” Driver callbacks (wdog_fn) invoked under global spinlock w/ interrupts disabled

See VERDICT.md for the full root-cause analysis and reachability.

Reproduce

./build.sh && ./run.sh

(For DF-0236 the bug is confirmed at source level; on this QEMU guest the vulnerable path is latent / timing-dependent β€” see VERDICT.md "Reachability".)

Fix

fix.diff is a standalone git apply\ -able patch. Validated to apply clean (git apply --check) and compile in a single all-fixes kernel build (all_fixes_build.log, rc=0, no errors).

VERDICT.md verdict lock-held-during-callback trace + reachability
↓ download raw

DF-0236 β€” Driver callbacks (wdog_fn) invoked under global spinlock w/ interrupts disabled

Verdict: REPRODUCED (source-level) / LATENT on this guest. Impact: DoS / latency β€” a sleeping/stalling driver callback deadlocks wdogmtx and stalls the system; not memory corruption, no escalation chain.

The bug

sys/kern/kern_wdog.c, wdog_reset_all():

90: static void
91: wdog_reset_all(void *unused)
92: {
...
96:     spin_lock(&wdogmtx);                 /* global spinlock, raises IPL */
97:     if (LIST_EMPTY(&wdoglist))
98:         goto done;
99:     LIST_FOREACH(wd, &wdoglist, link) {
100:        period = wdog_reset(wd);          /* -> wd->wdog_fn(wd->arg, wd->period) */
...
104:    if (wdog_auto_enable) {
105:        callout_reset(&wdog_callout, min_period * hz / 2, wdog_reset_all, NULL);
106:    }
...
111:    spin_unlock(&wdogmtx);

wdog_reset(wd) (line 87) calls wd->wdog_fn(wd->arg, wd->period) β€” arbitrary driver code β€” while wdogmtx is held and interrupts are disabled (spin_lock raises IPL). Any callback that sleeps, blocks on a lock, or performs slow MMIO will: - deadlock the global wdogmtx (other CPUs hitting wdog_register/wdog_unregister/the sysctls spin), - spike interrupt-disabled latency system-wide, - and the self-rescheduling callout_reset(&wdog_callout, ..., wdog_reset_all, ...) re-enters the same locked-callback path.

Reachability on this guest (LATENT)

Same as DF-0234: the only wdog_register() callers are amdsbwd.c and ichwd.c, neither present on this QEMU guest. wdoglist is empty, so wdog_reset_all early-returns and no callback is ever invoked. The locking defect is real and confirmed by trace; it is latent until a watchdog driver registers.

The fix

fix.diff snapshots the registered watchdog pointers into a small array under the spinlock, then spin_unlock()s before invoking any wdog_fn, then re-acquires the lock only to update wdog_auto_period and arm the callout. This keeps list traversal consistent while guaranteeing driver callbacks run lock-free.

Kernel refs

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. wdog_reset_all callbacks under spinlock. No HW watchdog. Compile validated.