mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #85] kernel: vnode_pageout reads v_vm_info->vnode_size without a NULL check after a forced reclaim #77
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#77
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 30, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/85
Left open by #84 (and #81).
vnode_pageout(vm/vnode_pager.c~863-867, ffs-perfa2a72069f) clamps the pageout size againstvp->v_vm_info->vnode_sizebefore it locks the vnode, with no check thatv_vm_infois still there.A user mmap object (or exec text) can outlive its vnode's vm_info: a forced unmount's vclean runs
vm_info_freeand setsv_vm_infoto NULL while the VM object still has dirty pages. A later pageout of such a page (pageout daemon, object terminate, msync) then dereferences NULL.#81 already guards the error store after
VOP_PAGEOUT(~927), and #84 guards both reads invnode_pagein(~757/788). This is the remaining unguarded read in the pager.Expected: with
v_vm_infoNULL, skip the clamp and let the write fail through deadfs, so the page is dropped and the pageout returns PAGER_ERROR, asvnode_pageinnow does. No panic.Reproduce: mmap a file shared and writable from a forced-unmountable mount (loopback NFS or a scratch UFS), dirty pages,
umount -f, then force a pageout (memory pressure ormsyncon the stale mapping).@raynorpat commented on GitHub (Oct 31, 2026):
Fixed by
278d00c75, merged into ffs-perf in23c1dd5f6.Root cause.
vnode_pageout's MACH_NBC size clamp (vm/vnode_pager.c:855-867) readvp->v_vm_info->vnode_sizeafter a forced reclaim had setv_vm_infoto NULL. That happens on every pageout of a stale page, not just in a race.0xf000ff54for all 16 dirty pages, once at msync and once at munmap.Fix. Skip the clamp when
v_vm_infois NULL, asvnode_pageindoes, and let deadfs fail the write.Also guarded. The audit of every
v_vm_infouse left invnode_pager.cfound three more reads that matter only after a forced unmount of a volume holding a swap file (untested):vnode_sizegrowth (:883-884);vnode_pager_truncate(:1335, :1345). Thevn_lockthere can wait out a reclaim.The rest are already safe.
What the user sees (same before and after; there was no panic before either):
msyncreturns EIO;Verified on the kernel built from
1d3cb1f80(cksum 151843857):mx.sh: dirty a shared mapping,umount -f, then msync/munmap): msync EIO, SIGBUS, no panic. The probe kernel no longer shows the NULL read.s4x.sh5/5.rp.shandrp2.sh3/3 each.check-proc,check-mmap,check-vm,check-fspass on UFS and/mnt/nfs. The NFS plain unmount is clean.stress-vm pressure(640m, swap growing to about 420 MB): 2/3 pass. 1 run hit the 600 s timeout with the build guest running at the same time; base timed out the same way.Left open: the pageout daemon retries a dirty page of a reclaimed vnode until it is unmapped. Each retry is a cheap deadfs EIO.