From nobody Tue May 13 12:51:03 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Zxbtw0Chbz5wp4s; Tue, 13 May 2025 12:51:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Zxbtv2glJz40nK; Tue, 13 May 2025 12:51:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747140663; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4qgPHxbnU0SshZGnbdk98SzrlGTrgxNSYW1N+5b2Ias=; b=iXUhcZZN3B/iuITFj5YbynFUTHVwSp9Kg+MELKz+Kuytv+fuDPMJ3WIZ5B7q3K7sSuqb/K kXnKW1kBSCO3+aR1XGGKLcWrb2NrqnVWoLODcWgv1sC+0RYoa+Ti8iYgrnAWZFQpeUbnUF vu46veExpHGTm9Bow2krpmUEv6fkmOGirsxS7wQdfsWolNtm9eM0k6SQOBVbgWFPjwGeCY 9JOLQIG69nkebhD6NWh1lCwAyMiSi/pBc6qdoodelF2So6h7MG/xwVKdOOrWG+QIRm13Kk T7RFn68m5KhgJJRuMg6FI2RWKXFv6r/1ZwA1a6UGU45TG2JqUh5E5oGfJxZt3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747140663; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4qgPHxbnU0SshZGnbdk98SzrlGTrgxNSYW1N+5b2Ias=; b=FE0p3KYrVjGI79i/shbTxHmopbbpo5FNxyu53GTL0ef8ArPt5ETxyD/dj7edzXdT0bLjUc 5G1fBRwmiQPlUy559Dl/E9lPUpIi/1ifxTPfUuDV7imi9N/4b7/bVMEZR9A1Xx3zNQJDBZ VC7p04oXEtj/Vy6/zMMADSa+kCAj+QQzb0F9D6wmEIJ3ja3Rhl34TKUZPlNQQrd8sTwxi4 7MOb/0fPZ9D7Bgxm8nRMQjY2t+2hKl9TCQe04xFi6WIby2sp89S0W89svEjv/fygdr1iL1 iXefzQHCWSWGqgMiFNFtUZ0+4CC0r4rwIKg6uYpNFmxq1o6tG0kvhQrSCSVwXA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1747140663; a=rsa-sha256; cv=none; b=gzZRdek53ghaAnlk5dlL3A4IegZL2RWtdcSGa2Ogy9Bs5LVn0ftMJ72DzbC2lFpf8xYrLX Y14qB38LkLI6tmUk16epnaFIl5RyF0Tqbb+gfBxm4rtC7ZCQKNBWqpXbPhmJGGwN9JgNCn K/A/HiYpSFRk1EyhtR0SDCzFQ43h163/d2LJehPc7PiR5P0mgb7RsrpsxvOOt9Py7SP3it SUB3BlyF9P69bVFLVaZav93QXk3NlKIoOBOfS5mQMD+uu9Q54l58LZZ69d71kUaYPXWQU2 ElaWaleCJr1I8ynk59x8tM5toKAfHoPw20CXT/NUKt4Q47BPavOkw9ZPDR+xMg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Zxbtv1xPRznBx; Tue, 13 May 2025 12:51:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54DCp3ku087125; Tue, 13 May 2025 12:51:03 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54DCp37v087122; Tue, 13 May 2025 12:51:03 GMT (envelope-from git) Date: Tue, 13 May 2025 12:51:03 GMT Message-Id: <202505131251.54DCp37v087122@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: bd20de7d16c7 - stable/14 - vm_fault: Defer marking COW pages valid List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: bd20de7d16c768f00419602a0eb2ed93b942bf0e Auto-Submitted: auto-generated The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=bd20de7d16c768f00419602a0eb2ed93b942bf0e commit bd20de7d16c768f00419602a0eb2ed93b942bf0e Author: Mark Johnston AuthorDate: 2025-04-13 16:09:31 +0000 Commit: Mark Johnston CommitDate: 2025-05-13 12:50:51 +0000 vm_fault: Defer marking COW pages valid Suppose an object O has two shadow objects S1, S2 mapped into processes P1, P2. Suppose a page resident in O is mapped read-only into P1. Now suppose that P1 writes to the page, triggering a COW fault: it allocates a new page in S1 and copies the page, then marks it valid. If the page in O was busy when initially looked up, P1 would have to release the map lock and sleep first. Then, after handling COW, P1 must re-check the map lookup because locks were dropped. Suppose the map indeed changed, so P1 has to retry the fault. At this point, the mapped page in O is shadowed by a valid page in S1. If P2 exits, S2 will be deallocated, resulting in a collapse of O into S1. In this case, because the mapped page is shadowed, P2 will free it, but that is illegal; this triggers a "freeing mapped page" assertion in invariants kernels. Fix the problem by deferring the vm_page_valid() call which marks the COW copy valid: only mark it once we know that the fault handler will succeed. It's okay to leave an invalid page in the top-level object; it will be freed when the fault is retried, and vm_object_collapse_scan() will similarly free invalid pages in the shadow object. Reviewed by: kib MFC after: 1 month Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D49758 (cherry picked from commit c98367641991019bac0e8cd55b70682171820534) --- sys/vm/vm_fault.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index dd044d27f00f..9d7c5d452a0b 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -1050,14 +1050,14 @@ vm_fault_cow(struct faultstate *fs) * Oh, well, lets copy it. */ pmap_copy_page(fs->m, fs->first_m); - vm_page_valid(fs->first_m); if (fs->wired && (fs->fault_flags & VM_FAULT_WIRE) == 0) { vm_page_wire(fs->first_m); vm_page_unwire(fs->m, PQ_INACTIVE); } /* - * Save the cow page to be released after - * pmap_enter is complete. + * Save the COW page to be released after pmap_enter is + * complete. The new copy will be marked valid when we're ready + * to map it. */ fs->m_cow = fs->m; fs->m = NULL; @@ -1740,6 +1740,19 @@ found: if (hardfault) fs.entry->next_read = vaddr + ptoa(ahead) + PAGE_SIZE; + /* + * If the page to be mapped was copied from a backing object, we defer + * marking it valid until here, where the fault handler is guaranteed to + * succeed. Otherwise we can end up with a shadowed, mapped page in the + * backing object, which violates an invariant of vm_object_collapse() + * that shadowed pages are not mapped. + */ + if (fs.m_cow != NULL) { + KASSERT(vm_page_none_valid(fs.m), + ("vm_fault: page %p is already valid", fs.m_cow)); + vm_page_valid(fs.m); + } + /* * Page must be completely valid or it is not fit to * map into user space. vm_pager_get_pages() ensures this.