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