From owner-svn-src-all@freebsd.org Wed Sep 9 06:19:34 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 43DEAA008EA; Wed, 9 Sep 2015 06:19:34 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1ACE21D52; Wed, 9 Sep 2015 06:19:34 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t896JXSg021956; Wed, 9 Sep 2015 06:19:33 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t896JX5r021955; Wed, 9 Sep 2015 06:19:33 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201509090619.t896JX5r021955@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Wed, 9 Sep 2015 06:19:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287591 - head/sys/vm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Sep 2015 06:19:34 -0000 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