From 724bc23da1a9c40768723a4796060c921dbaf224 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 15 Mar 2021 16:02:17 -0400 Subject: vm_fault: Shoot down multiply mapped COW source page mappings Reviewed by: kib, rlibby Discussed with: alc Approved by: re (so, implicit) Approved by: so Security: CVE-2021-29626 Security: FreeBSD-SA-21:08.vm (cherry picked from commit 982693bb729badac4e65ecd59772979f2849a2b2) (cherry picked from commit 2e08308d62f381312b3da9dac8970dcdad4b3f2d) --- sys/vm/vm_fault.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index da7b1f1d2d8e..8b212f3f84e5 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -894,6 +894,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 @@ -957,11 +960,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); /* -- cgit v1.2.3