svn commit: r345324 - head/sys/vm

Konstantin Belousov kib at FreeBSD.org
Wed Mar 20 13:07:58 UTC 2019


Author: kib
Date: Wed Mar 20 13:07:57 2019
New Revision: 345324
URL: https://svnweb.freebsd.org/changeset/base/345324

Log:
  vm_fault_copy_entry: accept invalid source pages.
  
  Either msync(MS_INVALIDATE) or the object unlock during vnode
  truncation can expose invalid pages backing wired entries.  Accept
  them, but do not install them into destrination pmap.  We must create
  copied pages in the copy case, because e.g. vm_object_unwire() expects
  that the entry is fully backed.
  
  Reported by:	syzkaller, via emaste
  Reported by:	syzbot+514d40ce757a3f8b15bc at syzkaller.appspotmail.com
  Reviewed by:	markj
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D19615

Modified:
  head/sys/vm/vm_fault.c

Modified: head/sys/vm/vm_fault.c
==============================================================================
--- head/sys/vm/vm_fault.c	Wed Mar 20 10:36:58 2019	(r345323)
+++ head/sys/vm/vm_fault.c	Wed Mar 20 13:07:57 2019	(r345324)
@@ -1757,8 +1757,7 @@ again:
 			}
 			pmap_copy_page(src_m, dst_m);
 			VM_OBJECT_RUNLOCK(object);
-			dst_m->valid = VM_PAGE_BITS_ALL;
-			dst_m->dirty = VM_PAGE_BITS_ALL;
+			dst_m->dirty = dst_m->valid = src_m->valid;
 		} else {
 			dst_m = src_m;
 			if (vm_page_sleep_if_busy(dst_m, "fltupg"))
@@ -1771,8 +1770,6 @@ again:
 				 */
 				break;
 			vm_page_xbusy(dst_m);
-			KASSERT(dst_m->valid == VM_PAGE_BITS_ALL,
-			    ("invalid dst page %p", dst_m));
 		}
 		VM_OBJECT_WUNLOCK(dst_object);
 
@@ -1780,9 +1777,18 @@ again:
 		 * Enter it in the pmap. If a wired, copy-on-write
 		 * mapping is being replaced by a write-enabled
 		 * mapping, then wire that new mapping.
+		 *
+		 * The page can be invalid if the user called
+		 * msync(MS_INVALIDATE) or truncated the backing vnode
+		 * or shared memory object.  In this case, do not
+		 * insert it into pmap, but still do the copy so that
+		 * all copies of the wired map entry have similar
+		 * backing pages.
 		 */
-		pmap_enter(dst_map->pmap, vaddr, dst_m, prot,
-		    access | (upgrade ? PMAP_ENTER_WIRED : 0), 0);
+		if (dst_m->valid == VM_PAGE_BITS_ALL) {
+			pmap_enter(dst_map->pmap, vaddr, dst_m, prot,
+			    access | (upgrade ? PMAP_ENTER_WIRED : 0), 0);
+		}
 
 		/*
 		 * Mark it no longer busy, and put it on the active list.


More information about the svn-src-all mailing list