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)
PoC verification
Evidence pack
findings/poc/DF-0236 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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).
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
sys/kern/kern_wdog.c:96βspin_lock(&wdogmtx)sys/kern/kern_wdog.c:99-100βwdog_reset()βwdog_fn()called under the locksys/kern/kern_wdog.c:87βwdog_resetinvokeswd->wdog_fnsys/dev/misc/amdsbwd/amdsbwd.c:519,sys/dev/misc/ichwd/ichwd.c:593β only registrants
Fix verification
not_testablecompile 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.
No comments yet.