git: 982693bb729b - main - vm_fault: Shoot down multiply mapped COW source page mappings

Mark Johnston markj at FreeBSD.org
Tue Apr 6 19:18:04 UTC 2021


The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=982693bb729badac4e65ecd59772979f2849a2b2

commit 982693bb729badac4e65ecd59772979f2849a2b2
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-03-15 20:02:17 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-04-06 18:49:28 +0000

    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
---
 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 dd112feefdcd..c9f3cdf2e4f6 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -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);
 
 	/*


More information about the dev-commits-src-all mailing list