Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Oct 2023 23:53:49 GMT
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: c3dc958cacd8 - stable/13 - vfs cache: plug a hypothetical corner case when freeing
Message-ID:  <202310132353.39DNrnt9032001@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=c3dc958cacd819c9fe989477371f01c187873cc0

commit c3dc958cacd819c9fe989477371f01c187873cc0
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2023-09-23 02:04:06 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2023-10-13 23:48:12 +0000

    vfs cache: plug a hypothetical corner case when freeing
    
    cache_zap_unlocked_bucket is called with a bunch of addresses and
    without any locks held, forcing it to revalidate everything from
    scratch.
    
    It did not account for a case where the entry is reallocated with
    everything the same except for the target vnode.
    
    Should the target use a different lock than the one expected, freeing
    would proceed without being properly synchronized.
    
    Note this is almost impossible to happen in practice.
    
    (cherry picked from commit 0f15054f7990f9c772bea34778a8838aa05ebed8)
---
 sys/kern/vfs_cache.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 1d52b2e63169..49e66803a1d1 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1649,6 +1649,7 @@ cache_zap_unlocked_bucket(struct namecache *ncp, struct componentname *cnp,
     struct mtx *blp)
 {
 	struct namecache *rncp;
+	struct mtx *rvlp;
 
 	cache_assert_bucket_unlocked(ncp);
 
@@ -1661,14 +1662,24 @@ cache_zap_unlocked_bucket(struct namecache *ncp, struct componentname *cnp,
 		    !bcmp(rncp->nc_name, cnp->cn_nameptr, rncp->nc_nlen))
 			break;
 	}
-	if (rncp != NULL) {
-		cache_zap_locked(rncp);
-		mtx_unlock(blp);
-		cache_unlock_vnodes(dvlp, vlp);
-		atomic_add_long(&zap_bucket_relock_success, 1);
-		return (0);
-	}
 
+	if (rncp == NULL)
+		goto out_mismatch;
+
+	if (!(ncp->nc_flag & NCF_NEGATIVE))
+		rvlp = VP2VNODELOCK(rncp->nc_vp);
+	else
+		rvlp = NULL;
+	if (rvlp != vlp)
+		goto out_mismatch;
+
+	cache_zap_locked(rncp);
+	mtx_unlock(blp);
+	cache_unlock_vnodes(dvlp, vlp);
+	atomic_add_long(&zap_bucket_relock_success, 1);
+	return (0);
+
+out_mismatch:
 	mtx_unlock(blp);
 	cache_unlock_vnodes(dvlp, vlp);
 	return (EAGAIN);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202310132353.39DNrnt9032001>