git: 0c09f4b0cc63 - main - cache: work around corner case of dvp == tvp in cache_fplookup_final_modifying

Mateusz Guzik mjg at FreeBSD.org
Mon Dec 28 21:39:33 UTC 2020


The branch main has been updated by mjg:

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

commit 0c09f4b0cc633750a3cbf724e8590ed9d4ef92e1
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2020-12-28 21:24:53 +0000
Commit:     Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2020-12-28 21:38:20 +0000

    cache: work around corner case of dvp == tvp in cache_fplookup_final_modifying
    
    Fixes a panic where the kernel would unlock an unheld lock coming from
    rename looking up "foo/." as the source.
    
    Reported by:    markj (syzkaller)
---
 sys/kern/vfs_cache.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 4513e4dc970f..94d622867425 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -4063,6 +4063,19 @@ cache_fplookup_final_modifying(struct cache_fpl *fpl)
 		return (cache_fpl_handled(fpl, 0));
 	}
 
+	/*
+	 * There are very hairy corner cases concerning various flag combinations
+	 * and locking state. In particular here we only hold one lock instead of
+	 * two.
+	 *
+	 * Skip the complexity as it is of no significance for normal workloads.
+	 */
+	if (__predict_false(tvp == dvp)) {
+		vput(dvp);
+		vrele(tvp);
+		return (cache_fpl_aborted(fpl));
+	}
+
 	/*
 	 * Check if the target is either a symlink or a mount point.
 	 * Since we expect this to be the terminal vnode it should


More information about the dev-commits-src-all mailing list