Page MenuHomeFreeBSD

device_pager: Avoid double-insertion of pages into the pager list
ClosedPublic

Authored by markj on Jun 22 2026, 2:47 PM.
Tags
None
Referenced Files
F165464536: D57743.id180303.diff
Sat, Aug 8, 8:32 AM
F165410867: D57743.id180990.diff
Sat, Aug 8, 2:26 AM
F165403213: D57743.diff
Sat, Aug 8, 1:06 AM
Unknown Object (File)
Mon, Aug 3, 3:37 AM
Unknown Object (File)
Mon, Aug 3, 1:17 AM
Unknown Object (File)
Mon, Aug 3, 1:13 AM
Unknown Object (File)
Sun, Aug 2, 12:57 AM
Unknown Object (File)
Thu, Jul 30, 6:28 AM

Details

Summary

Unmanaged device pager objects maintain a linked list of pages that were
returned from the fault handler. Initially, such pages are valid, but
msync(MS_INVALIDATE) can mark them invalid (and clean). They are not
removed from page tables (since they are unmanaged), but a subsequent
mlock() call can trigger a page fault that is handled by the pager.
dev_pager_getpages() then re-inserts the page into the linked list even
though it's already present there.

This patch fixes the problem by removing the linked list. OBJ_PG_DTOR
is set, so vm_object_terminate_pages() does nothing, and
dev_pager_dealloc() instead handles cleanup of the object.

Add a regression test case which triggers a queue.h assertion failure in
unpatched kernels.

Note, in stable branches we should avoid changing the layout of struct
vm_object.

Reported by: slidybat

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj held this revision as a draft.
markj changed the visibility from "Public (No Login Required)" to "Subscribers".Jun 22 2026, 2:47 PM
markj changed the edit policy from "All Users" to "Subscribers".
markj removed a subscriber: imp.
markj published this revision for review.Jun 22 2026, 2:57 PM
markj added reviewers: alc, kib, dougm.
markj added subscribers: secteam, alc, kib, dougm.

So the patch shrinks struct vm_object by single pointer, am I right?

sys/vm/device_pager.c
355

How the vm_page_free() case could occur at all?

In D57743#1323874, @kib wrote:

So the patch shrinks struct vm_object by single pointer, am I right?

I believe so.

sys/vm/device_pager.c
355

vm_fault will initially insert some newly allocated pages into the object. Typically they are replaced with fictitious pages by the device pager, but I suspect it's possible that some error in between can cause invalid pages to be left behind in the object.

Side note. Using unmanaged device pager for the allocated regular pages is the bug by itself. E.g. the driver cannot be unloaded or at least the pages cannot be freed.

So all pagers used by sound(4) should be converted to managed cdev, or to something else. It might be that the phys pager is the better choice for all types of mmaps there.

In D57743#1323881, @kib wrote:

Side note. Using unmanaged device pager for the allocated regular pages is the bug by itself. E.g. the driver cannot be unloaded or at least the pages cannot be freed.

So all pagers used by sound(4) should be converted to managed cdev, or to something else. It might be that the phys pager is the better choice for all types of mmaps there.

I agree. I guess some of these drivers existed before OBJT_PHYS was introduced in 2000.

(Note, the regression test uses /dev/devstat, not a sound driver. It just uses the devfs infrastructure for mmap.)

kib added inline comments.
sys/vm/device_pager.c
355

Worth a comment IMO.

This revision is now accepted and ready to land.Jun 22 2026, 4:02 PM
markj marked an inline comment as done.

Add a comment

This revision now requires review to proceed.Jun 22 2026, 4:47 PM
This revision is now accepted and ready to land.Jun 22 2026, 4:49 PM
markj changed the visibility from "Subscribers" to "Public (No Login Required)".Fri, Jul 24, 7:08 PM
markj changed the edit policy from "Subscribers" to "All Users".