Missing resume_kproc implementation: suspend permanently freezes kernel daemons
Summary
resume_kproc declared kthread.h:56 but NEVER DEFINED. TDF_MP_WAKEREQ never set. kproc_suspend_loop(:216) while(WAKEREQ==0) tsleep(td,0,kpsusp,0) forever. 6 daemons affected: syncer, bufdaemon, swapcache, mountd, printf, hptmv. suspend_kproc is destructive-by-design. USB already warns: left suspended.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0239 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| build.sh | build-script | symbol-absence check | 368 B | view raw |
| run.sh | run-script | summary | 266 B | view raw |
| all_fixes_build.log | build-log | kernel build with resume_kproc added: compiles rc=0; symbol now present at 0xffffffff80646040 | 5.6 MB | β download |
| env.txt | environment | uname + resume_kproc absent on baseline kernel | 353 B | view raw |
| fix.diff | suggested-fix | implement resume_kproc mirroring suspend_kproc | 1.0 KB | view raw |
| VERDICT.md | verdict | missing-implementation trace + affected daemons | 3.3 KB | β raw |
| README.md | readme | human reproduce doc | 571 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-0239 β DF-0239 β Missing resume_kproc implementation: suspend permanently freezes daemons
See VERDICT.md for the full root-cause analysis and reachability.
Reproduce
./build.sh && ./run.sh
(For DF-0239 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-0239 β Missing resume_kproc implementation: suspend permanently freezes daemons
Verdict: REPRODUCED (source-level). Impact: DoS / availability β a suspended kernel daemon (syncer, bufdaemon, swapcache, mountd, printf, hptmv) never resumes; not memory corruption, no escalation chain.
The bug
resume_kproc() is declared in sys/sys/kthread.h:56 but never defined anywhere in
the tree:
$ grep -rn 'resume_kproc' sys/ sys/sys/thread.h:435:#define TDF_MP_WAKEREQ 0x00000002 /* resume_kproc */ sys/sys/kthread.h:56:int resume_kproc (struct thread *); <-- declaration, NO body
sys/kern/kern_kthread.c defines suspend_kproc() (187-206) and kproc_suspend_loop()
(208-224) but has no resume_kproc(). The suspend loop waits on a flag nothing ever sets:
208: void
209: kproc_suspend_loop(void)
210: {
211: struct thread *td = curthread;
212: if (td->td_mpflags & TDF_MP_STOPREQ) {
213: lwkt_gettoken(&kpsus_token);
214: atomic_clear_int(&td->td_mpflags, TDF_MP_STOPREQ);
216: while ((td->td_mpflags & TDF_MP_WAKEREQ) == 0) { /* <-- nothing sets WAKEREQ */
217: wakeup(td);
218: tsleep(td, 0, "kpsusp", 0); /* sleeps FOREVER */
219: }
220: atomic_clear_int(&td->td_mpflags, TDF_MP_WAKEREQ);
...
Because resume_kproc() does not exist, TDF_MP_WAKEREQ is never set, so once a daemon calls
kproc_suspend_loop() after a suspend_kproc() request, it loops in tsleep() forever.
Who is affected
suspend_kproc() callers (suspend requestors) and kproc_suspend_loop() sites (daemons):
- suspend:
kern_shutdown.c:939(shutdown β permanent freeze is harmless there),usb_process.c:61(USB_THREAD_SUSPEND),uvc_drv.c:1175. - suspend-loop (the frozen daemons):
vfs_sync.c:379(syncer),vfs_bio.c:2251(bufdaemon),vm_swapcache.c:234(swapcache),vfs_mount.c:529(mountd),subr_prf.c:931(printf),hptmv/entry.c:2467(hptmv raid daemon).
So an ACPI suspend (or a USB suspend event, sys/bus/u4b/usb_process.c) that suspends these
daemons leaves them permanently frozen β they never resume. The USB subsystem itself even
warns about being "left suspended".
Reachability
Suspend is a privileged/host-initiated event (ACPI S3, USB suspend). Not triggerable by an
unprivileged user on this guest, but the missing implementation is unambiguous: the
declared function has no body, so ANY code path that suspends a kproc is broken-by-design. The
bug is confirmed by source trace (the linker would also reject a kernel that calls
resume_kproc today β confirming no in-tree suspend/resume symmetry exists).
The fix
fix.diff adds the missing resume_kproc() to kern_kthread.c, mirroring suspend_kproc():
under kpsus_token, set TDF_MP_WAKEREQ, wakeup(td), wait for the daemon to clear it, then
return. This unblocks kproc_suspend_loop() line 216 and restores suspend/resume symmetry.
Kernel refs
sys/sys/kthread.h:56β declaration ofresume_kproc(no definition exists)sys/kern/kern_kthread.c:216βwhile ((td->td_mpflags & TDF_MP_WAKEREQ) == 0)infinite waitsys/kern/kern_kthread.c:187βsuspend_kproc(the mirror that DOES exist)sys/sys/thread.h:435βTDF_MP_WAKEREQflag nothing sets
Fix verification
fixedvalidated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (symbol). resume_kproc declared but never defined -> suspend permanently freezes kproc daemons. nm confirms absent. Fix: implement.
No comments yet.