Four more raw vm_page_t-pointer kprintfs on attacker-triggerable pagedaemon race-recovery paths (rebusy A/B/C and the scan_cache find/busy warning) disclose kernel heap addresses into the world-readable msgbuf
Summary
vm_pageout_page prints 'rebusy %p failed(A)/(B)/(C)' when a page moved queues/objects/handle, became invalid, or was cleaned by a competing flush across its blocking vget window (:1340/:1350/:1356); vm_pageout_scan_cache prints 'WARNING! page race during find/busy: %p' (:1728). All four leak a raw vm_page_t (vm_page_array address) plus page state to the console/msgbuf readable by any local user (dmesg world-executable, verified). Same class as DF-2689 but four distinct sites; strings verified present in the running guest kernel. Honest verdict: NOT reproduced β 8 runs / 5 rig designs / ~25 min under verified daemon pressure (1862 wakeups, 1.31M pages examined) never fired; vm.pageout_lock_miss stayed 0 β the guarded interleavings are empirically rare on this fast-disk guest. Defect stands by inspection; full rig history retained for re-testing on slower/busier hardware. Delete-the-kprintfs fix git-apply-clean.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5813 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| df5813_leakstress.c | β | 5.8 KB | view raw | |
| build.sh | β | 112 B | view raw | |
| run.sh | β | 182 B | view raw | |
| build.log | β | 183 B | view raw | |
| run.log | β | 1.2 KB | view raw | |
| strings_check.txt | β | 447 B | view raw | |
| fix.diff | β | 1.0 KB | view raw | |
| verdict.json | β | 3.6 KB | view raw | |
| README.md | β | 2.7 KB | β raw |
DF-5813 β four more raw-kernel-pointer kprintfs on pagedaemon race-recovery paths
Finding: vm_pageout_page() and vm_pageout_scan_cache() print raw
vm_page_t pointers (physmap/vm_page_array addresses) plus page state to
the console/msgbuf on race-recovery paths:
sys/vm/vm_pageout.c:1340βvm_pageout_page: rebusy %p failed(A)(page moved queues / changed object / vnode handle changed across the blockingvget()window),sys/vm/vm_pageout.c:1350β... failed(B)(page became invalid),sys/vm/vm_pageout.c:1356β... failed(C)(page was cleaned by a competing flush duringvget()),sys/vm/vm_pageout.c:1728βWARNING! page race during find/busy: %p queue == %d dirty=%02x(PQ_CACHE page raced betweenvm_page_list_find()andvm_page_busy_try()).
Sibling of DF-2689 (which covers only the scan_hold print at :1932).
Verification verdict: not_reproduced (race never fired on this guest)
Verified on the guest (DragonFly 6.5-DEVELOPMENT #0, X86_64_GENERIC):
- All four format strings ARE in the running kernel:
strings /boot/kernel/kernel | grep -E 'failed\((A|B|C)\)|page race during find|HOLD->FREE'β 1/1/1/1. - The msgbuf is world-readable by an unprivileged user (
test/maxxuid 1001/1002 ran/sbin/dmesgsuccessfully) β so when the prints fire, the pointer is disclosed to any local user. - Five adversarial stress rigs (~25 min wall, ~2 GB/s of vnode-page
churn under sustained pagedaemon pressure) did NOT hit the races:
- v1: mmap+msync(MS_ASYNC)+madvise churn + ftruncate + 2.3 GB anon hog
- v2: 6β8 files Γ writers/syncer(MS_SYNC+MS_INVALIDATE)/cacher + hogs
- v3: persistent dirty RW maps (writers never clean) + 1.4 GB hog
- v4: dirty-then-ABANDON cycling (WINATCFLS state machine) + 2.6 GB hog
- file placement on UFS (/boot) and HAMMER2 (/), hog 500β2700 MB
During the rigs the pagedaemon was demonstrably active (1862 wakeups,
1.31 M pages examined, 295 k pages freed by daemon, vnode putpages
counter +60 k) β but
vm.pageout_lock_missstayed 0 (the daemon'svget()in the laundering branch never even timed out on this fast-disk single-tenant guest) and none of the four prints fired.
Conclusion: the disclosure is certain by inspection (the prints are unconditional on their paths and dmesg is world-readable), but the guarded interleavings are empirically rare on this hardware; the PoC is recorded as not_reproduced rather than claimed without a firing.
Files
df5813_leakstress.cβ v4 trigger (final; see header for design notes)build.sh/run.shrun.logβ decisive rig run output (v4, 300 s, markers stayed 0)strings_check.txtβ kernel-binary + dmesg-permission verificationverdict.jsonβ machine verdict
Fix verification
not_testableNo kernel fix-build performed: finding did not reproduce (race too rare on this guest) and severity is Info; fix is a one-line kprintf removal validated by inspection.
fix.diff authored against sys/vm/vm_pageout.c (not applied to sys/).
Confirmed kernel references
Detail
Evidence (decisive lines)
['findings/poc/DF-5813/strings_check.txt β all 4 format strings in /boot/kernel/kernel; unprivileged dmesg works', 'findings/poc/DF-5813/run.log β 5 rig designs, all runs markers=0, pageout_lock_miss=0', 'sys/vm/vm_pageout.c:1262-1359 β the vget window and the (A)/(B)/(C) recovery prints', 'sys/vm/vm_pageout.c:1727-1731 β the scan_cache find/busy race print', 'README.md β design rationale for why each rig targeted a specific print']
PoC changes
v1 crashed on ftruncate-beyond-EOF shared maps (SIGSEGV/SIGBUS); replaced truncation with msync(MS_INVALIDATE). v2/v3 kept pages too clean or too referenced to be deactivated; v4 implements dirty-then-ABANDON cycling so pages reach the daemon's WINATCFLS laundering branch while a syncer competes as cleaner.
Verified recommended fix
Delete the four kprintfs or strip the %p (keep a counter); mirrors the DF-2689 fix for :1932.
Verdict
The four pointer-printing kprintfs (vm_pageout.c:1340/1350/1356 'rebusy %p failed(A|B|C)' in vm_pageout_page() and :1728 'WARNING! page race during find/busy: %p' in vm_pageout_scan_cache()) are certain by inspection and verified present in the running guest kernel (strings check), and the msgbuf is world-readable by unprivileged users (verified: uid 1001/1002 ran /sbin/dmesg). However the guarded interleavings never fired on this guest: five adversarial stress-rig designs over ~25 minutes (mmap dirty/msync/madvise/ftruncate churn, persistent dirty maps, dirty-then-abandon WINATCFLS cycling, UFS and HAMMER2 targets, anon hogs 500-2700MB) kept the pagedaemon demonstrably busy (1862 wakeups, 1.31M pages examined, 295k freed, vnode putpages +60k) yet vm.pageout_lock_miss stayed 0 and no marker line ever appeared in dmesg. The defect (raw vm_page_t pointer disclosure on race-recovery paths, sibling of DF-2689 at :1932) stands as Info severity; the race is empirically rare on this fast-disk single-tenant guest, so the PoC is honestly recorded as not_reproduced with the full rig history for future re-testing on busier hardware.
No comments yet.