vm_fault: Shoot down multiply mapped COW source page mappings

Reviewed by:	kib, rlibby
Discussed with:	alc
Approved by:	so
Security:	CVE-2021-29626
Security:	FreeBSD-SA-21:08.vm
This commit is contained in:
Mark Johnston 2021-03-15 16:02:17 -04:00
parent afb6a168f8
commit 982693bb72

View File

@ -900,6 +900,9 @@ vm_fault_cow(struct faultstate *fs)
{
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
@ -963,11 +966,29 @@ vm_fault_cow(struct faultstate *fs)
*/
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);
/*