From nobody Fri Apr 18 14:00:20 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 4ZfGcP2bbgz5srP5; Fri, 18 Apr 2025 14:00:21 +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 "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZfGcN6qlVz42Gc; Fri, 18 Apr 2025 14:00:20 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744984821; 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=0t6zguvaKtAtfOPTD5IO/8GDpSfbse16nGngZyWFTrQ=; b=pl/BbV0Ficj0LGf/s7H+UWQOGn5mImsyiDtg9PqsLH5Gs1+LxXKG9NUY7LaXk4pF/9Ft+9 IoAFHphbqeRiiK30QUswcqvxLF3wlalcYsey436mCJEFU5fA3QA+7ou+3TOwdvmrtmcx7b BECi15rkbRlXFrgase7ndd5YbKMjnK/AoQ+w2/+Be3SP1tN1Soi9xucc9KxuY+1AAMw0gP 9RuCJoi0EnxBBabNTNQ39A/lRsIvt1tG4PP/ZVcpC5yD2FklEsK7L+766Lx5dErx2l/93N R7Ab54W3hwgncB3oO5KbgE42dERyW6v9wIUAHqEpY1jJAX0iMgZx9uPnbOstXA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1744984821; a=rsa-sha256; cv=none; b=tD79yMCQHaCcKoEOEOF8yD/09PIAMAYcgm/GJFEQJE3F1oK+8zJiyCW2dPHf87b2XoPZbl sb5pqr5jOMT3xBqNOYW+TM5M3eLiPBwGo3FQNtzypf/sbLfzkKZ7U2zQO423nQNYIJSQln JVV0calBBH/bXjyBNzkUK/e2tg2gN+VIbXrRBDYYgdP0trby69TZnO1asZjJ21P90acEZe FiElOXbK6X+QsYxhr48NriGj86b6vXnZ5ENYEVpunJafcefaDkzAKAExa3c5d3Aqf3tF6z s57EOZ0yscokHZTLfnZeEh9rsggrployKDHTwIDKdVDrgrdpDVkM3CCTjj/6cw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744984821; 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=0t6zguvaKtAtfOPTD5IO/8GDpSfbse16nGngZyWFTrQ=; b=qJYMh8xSgqPveJNVd8exLGrs9DoqX9AYM8+afkNcqtJ313Nwc3zDKx1ugTayF9SpQHeU1C yg7c5Yh2E+9Kk07RrkhKZNZExdjpkQu65jtfBfMvkc27bbucr7h3dKUSxbPw0LAV+2LbQq ue5uJHwup9G734G21EWUwRxef9aaShFRq997fu6bOW4p4iZr7h33XpVey1pWHGvKl9Mcga M5Oic7bPhQ4gU8X+Px1cFMr/Wb47gDAFmdMdh+gaJzZG4WfVByXo8Vx3ES1h9abIHBny7Y qiUgJnWuJO1faIUPdRJBWkGbHBs9ZHTbjkbKEQafvqIxCMql8WkBLurZ2PCBdw== 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 4ZfGcN6LkSzcbh; Fri, 18 Apr 2025 14:00:20 +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 53IE0KI0025825; Fri, 18 Apr 2025 14:00:20 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53IE0Kqn025822; Fri, 18 Apr 2025 14:00:20 GMT (envelope-from git) Date: Fri, 18 Apr 2025 14:00:20 GMT Message-Id: <202504181400.53IE0Kqn025822@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: afbe2bb9e939 - stable/14 - vm_object: Fix handling of wired map entries in vm_object_split() 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: afbe2bb9e939eee90033433c7172c14323917a54 Auto-Submitted: auto-generated The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=afbe2bb9e939eee90033433c7172c14323917a54 commit afbe2bb9e939eee90033433c7172c14323917a54 Author: Mark Johnston AuthorDate: 2025-04-04 20:29:25 +0000 Commit: Mark Johnston CommitDate: 2025-04-18 13:53:55 +0000 vm_object: Fix handling of wired map entries in vm_object_split() Suppose a vnode is mapped with MAP_PROT and MAP_PRIVATE, mlock() is called on the mapping, and then the vnode is truncated such that the last page of the mapping becomes invalid. The now-invalid page will be unmapped, but stays resident in the VM object to preserve the invariant that a range of pages mapped by a wired map entry is always resident. This invariant is checked by vm_object_unwire(), for example. Then, suppose that the mapping is upgraded to PROT_READ|PROT_WRITE. We will copy the invalid page into a new anonymous VM object. If the process then forks, vm_object_split() may then be called on the object. Upon encountering an invalid page, rather than moving it into the destination object, it is removed. However, this is wrong when the entry is wired, since the invalid page's wiring belongs to the map entry; this behaviour also violates the invariant mentioned above. Fix this by moving invalid pages into the destination object if the map entry is wired. In this case we must not dirty the page, so add a flag to vm_page_iter_rename() to control this. Reported by: syzkaller Reviewed by: dougm, kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D49443 (cherry picked from commit 43c1eb894a57ef30562a02708445c512610d4f02) --- sys/vm/vm_object.c | 11 ++++++++--- sys/vm/vm_page.c | 16 ++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 84e56b910809..a50dff22205b 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1601,16 +1601,21 @@ retry: } /* - * The page was left invalid. Likely placed there by + * If the page was left invalid, it was likely placed there by * an incomplete fault. Just remove and ignore. + * + * One other possibility is that the map entry is wired, in + * which case we must hang on to the page to avoid leaking it, + * as the map entry owns the wiring. This case can arise if the + * backing pager is truncated. */ - if (vm_page_none_valid(m)) { + if (vm_page_none_valid(m) && entry->wired_count == 0) { if (vm_page_remove(m)) vm_page_free(m); continue; } - /* vm_page_rename() will dirty the page. */ + /* vm_page_rename() will dirty the page if it is valid. */ if (vm_page_rename(m, new_object, idx)) { vm_page_xunbusy(m); VM_OBJECT_WUNLOCK(new_object); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 979a4b7b07fb..ac922f4a3bc8 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1833,15 +1833,10 @@ vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex, * Move the given memory entry from its * current object to the specified target object/offset. * - * Note: swap associated with the page must be invalidated by the move. We - * have to do this for several reasons: (1) we aren't freeing the - * page, (2) we are dirtying the page, (3) the VM system is probably - * moving the page from object A to B, and will then later move - * the backing store from A to B and we can't have a conflict. - * - * Note: we *always* dirty the page. It is necessary both for the - * fact that we moved it, and because we may be invalidating - * swap. + * This routine dirties the page if it is valid, as callers are expected to + * transfer backing storage only after moving the page. Dirtying the page + * ensures that the destination object retains the most recent copy of the + * page. * * The objects must be locked. */ @@ -1882,7 +1877,8 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex) m->object = new_object; vm_page_insert_radixdone(m, new_object, mpred); - vm_page_dirty(m); + if (vm_page_any_valid(m)) + vm_page_dirty(m); vm_pager_page_inserted(new_object, m); return (0); }