svn commit: r287591 - head/sys/vm

Konstantin Belousov kib at FreeBSD.org
Wed Sep 9 06:19:34 UTC 2015


Author: kib
Date: Wed Sep  9 06:19:33 2015
New Revision: 287591
URL: https://svnweb.freebsd.org/changeset/base/287591

Log:
  Remove a check which caused spurious SIGSEGV on usermode access to the
  mapped address without valid pte installed, when parallel wiring of
  the entry happen.  The entry must be copy on write.  If entry is COW
  but was already copied, and parallel wiring set
  MAP_ENTRY_IN_TRANSITION, vm_fault() would sleep waiting for the
  MAP_ENTRY_IN_TRANSITION flag to clear.  After that, the fault handler
  is restarted and vm_map_lookup() or vm_map_lookup_locked() trip over
  the check.  Note that this is race, if the address is accessed after
  the wiring is done, the entry does not fault at all.
  
  There is no reason in the current kernel to disallow write access to
  the COW wired entry if the entry permissions allow it.  Initially this
  was done in r24666, since that kernel did not supported proper
  copy-on-write for wired text, which was fixed in r199869.  The r251901
  revision re-introduced the r24666 fix for the current VM.
  
  Note that write access must clear MAP_ENTRY_NEEDS_COPY entry flag by
  performing COW.  In reverse, when MAP_ENTRY_NEEDS_COPY is set in
  vmspace_fork(), the MAP_ENTRY_USER_WIRED flag is cleared.  Put the
  assert stating the invariant, instead of returning the error.
  
  Reported and debugging help by:	peter
  Reviewed by:	alc
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/vm/vm_map.c

Modified: head/sys/vm/vm_map.c
==============================================================================
--- head/sys/vm/vm_map.c	Wed Sep  9 05:17:04 2015	(r287590)
+++ head/sys/vm/vm_map.c	Wed Sep  9 06:19:33 2015	(r287591)
@@ -3969,12 +3969,10 @@ RetryLookup:;
 		vm_map_unlock_read(map);
 		return (KERN_PROTECTION_FAILURE);
 	}
-	if ((entry->eflags & MAP_ENTRY_USER_WIRED) &&
-	    (entry->eflags & MAP_ENTRY_COW) &&
-	    (fault_type & VM_PROT_WRITE)) {
-		vm_map_unlock_read(map);
-		return (KERN_PROTECTION_FAILURE);
-	}
+	KASSERT((prot & VM_PROT_WRITE) == 0 || (entry->eflags &
+	    (MAP_ENTRY_USER_WIRED | MAP_ENTRY_NEEDS_COPY)) !=
+	    (MAP_ENTRY_USER_WIRED | MAP_ENTRY_NEEDS_COPY),
+	    ("entry %p flags %x", entry, entry->eflags));
 	if ((fault_typea & VM_PROT_COPY) != 0 &&
 	    (entry->max_protection & VM_PROT_WRITE) == 0 &&
 	    (entry->eflags & MAP_ENTRY_COW) == 0) {
@@ -4128,10 +4126,6 @@ vm_map_lookup_locked(vm_map_t *var_map,	
 	fault_type &= VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 	if ((fault_type & prot) != fault_type)
 		return (KERN_PROTECTION_FAILURE);
-	if ((entry->eflags & MAP_ENTRY_USER_WIRED) &&
-	    (entry->eflags & MAP_ENTRY_COW) &&
-	    (fault_type & VM_PROT_WRITE))
-		return (KERN_PROTECTION_FAILURE);
 
 	/*
 	 * If this page is not pageable, we have to get it for all possible


More information about the svn-src-head mailing list