From owner-dev-commits-src-main@freebsd.org Tue Jul 27 16:58:58 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 336F6663C0D; Tue, 27 Jul 2021 16:58:58 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GZ30f0hVNz4nD7; Tue, 27 Jul 2021 16:58:58 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 E0C9B661E; Tue, 27 Jul 2021 16:58:57 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 16RGwvQT083493; Tue, 27 Jul 2021 16:58:57 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 16RGwvF2083492; Tue, 27 Jul 2021 16:58:57 GMT (envelope-from git) Date: Tue, 27 Jul 2021 16:58:57 GMT Message-Id: <202107271658.16RGwvF2083492@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: d5b078163e0d - main - null_bypass(): prevent loosing the only reference to the lower vnode MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d5b078163e0d6bb2fe36f8e49a44853908d5e2db Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Jul 2021 16:58:58 -0000 The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=d5b078163e0d6bb2fe36f8e49a44853908d5e2db commit d5b078163e0d6bb2fe36f8e49a44853908d5e2db Author: Konstantin Belousov AuthorDate: 2021-07-20 00:53:08 +0000 Commit: Konstantin Belousov CommitDate: 2021-07-27 16:58:47 +0000 null_bypass(): prevent loosing the only reference to the lower vnode The upper vnode reference to the lower vnode is the only reference that keeps our pointer to the lower vnode alive. If lower vnode is relocked during the VOP call, upper vnode might become unlocked and reclaimed, which invalidates our reference. Add a transient vhold around VOP call. Reported and tested by: pho Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D31310 --- sys/fs/nullfs/null_vnops.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 0d5092f5e33d..47b0bda32b6b 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -266,6 +266,17 @@ null_bypass(struct vop_generic_args *ap) old_vps[i] = *this_vp_p; *(vps_p[i]) = NULLVPTOLOWERVP(*this_vp_p); + /* + * The upper vnode reference to the lower + * vnode is the only reference that keeps our + * pointer to the lower vnode alive. If lower + * vnode is relocked during the VOP call, + * upper vnode might become unlocked and + * reclaimed, which invalidates our reference. + * Add a transient hold around VOP call. + */ + vhold(*this_vp_p); + /* * XXX - Several operations have the side effect * of vrele'ing their vp's. We must account for @@ -300,6 +311,7 @@ null_bypass(struct vop_generic_args *ap) lvp = *(vps_p[i]); /* + * Get rid of the transient hold on lvp. * If lowervp was unlocked during VOP * operation, nullfs upper vnode could have * been reclaimed, which changes its v_vnlock @@ -307,11 +319,14 @@ null_bypass(struct vop_generic_args *ap) * must move lock ownership from lower to * upper (reclaimed) vnode. */ - if (lvp != NULLVP && - VOP_ISLOCKED(lvp) == LK_EXCLUSIVE && - old_vps[i]->v_vnlock != lvp->v_vnlock) { - VOP_UNLOCK(lvp); - VOP_LOCK(old_vps[i], LK_EXCLUSIVE | LK_RETRY); + if (lvp != NULLVP) { + if (VOP_ISLOCKED(lvp) == LK_EXCLUSIVE && + old_vps[i]->v_vnlock != lvp->v_vnlock) { + VOP_UNLOCK(lvp); + VOP_LOCK(old_vps[i], LK_EXCLUSIVE | + LK_RETRY); + } + vdrop(lvp); } *(vps_p[i]) = old_vps[i];