vm_fault: Shoot down multiply mapped COW source page mappings --- sys/vm/vm_fault.c.orig +++ sys/vm/vm_fault.c @@ -894,6 +894,9 @@ { bool is_first_object_locked; + KASSERT(fs->object != fs->first_object, + ("source and target COW objects are identical")); + /* * This allows pages to be virtually copied from a backing_object * into the first_object, where the backing object has no other @@ -957,11 +960,29 @@ */ fs->m_cow = fs->m; fs->m = NULL; + + /* + * Typically, the shadow object is either private to this + * address space (OBJ_ONEMAPPING) or its pages are read only. + * In the highly unusual case where the pages of a shadow object + * are read/write shared between this and other address spaces, + * we need to ensure that any pmap-level mappings to the + * original, copy-on-write page from the backing object are + * removed from those other address spaces. + * + * The flag check is racy, but this is tolerable: if + * OBJ_ONEMAPPING is cleared after the check, the busy state + * ensures that new mappings of m_cow can't be created. + * pmap_enter() will replace an existing mapping in the current + * address space. If OBJ_ONEMAPPING is set after the check, + * removing mappings will at worse trigger some unnecessary page + * faults. + */ + vm_page_assert_xbusied(fs->m_cow); + if ((fs->first_object->flags & OBJ_ONEMAPPING) == 0) + pmap_remove_all(fs->m_cow); } - /* - * fs->object != fs->first_object due to above - * conditional - */ + vm_object_pip_wakeup(fs->object); /*