[Bug 258932] panic: vm_page_free_prep: freeing mapped page

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 12 Jun 2022 17:48:24 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=258932

Mark Johnston <markj@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|bugs@FreeBSD.org            |markj@FreeBSD.org

--- Comment #16 from Mark Johnston <markj@FreeBSD.org> ---
After staring at a vmcore from bdrewery for a long time, I think I see the bug.
 It's a race which seems very hard to hit accidentally.

When the kernel crashed, we were removing and freeing pages from a VM object in
preparation for execve().  The OBJ_ONEMAPPING flag is set on the object, which
means only the current process has mapped the object, which why it's (supposed
to be) safe to free the object's pages.  The problem is that there are in fact
two mappings of the object: the other is in the parent tmux process, a COW
mapping.  So OBJ_ONEMAPPING should absolutely not be set!

When vmspace_fork() copies vm map entries from the parent into the child, it's
supposed to clear OBJ_ONEMAPPING.  For anonymous mappings, this happens in

  vmspace_fork() -> vm_map_copy_entry() -> vm_map_copy_swap_object()

vm_map_copy_entry() uses the following test to determine whether it's dealing
with a swap object:

  if (src_object->type == OBJT_DEFAULT || (src_object->flags & OBJ_SWAP) != 0)

This test is done racily, i.e., without the object lock, which isn't quite a
problem in itself, but with commit 4b8365d752ef4 it can produce false
negatives.  In particular, the first time a page in the object gets paged out,
swap_pager_put_pages() converts the object to a OBJT_SWAP object:

  object->type = OBJT_SWAP;
  vm_object_set_flag(object, OBJ_SWAP);

So there's a small window where object->type == OBJT_SWAP and OBJ_SWAP is
clear.

-- 
You are receiving this mail because:
You are the assignee for the bug.