git: b3e8bfd771b4 - stable/13 - cache: fix lockless absolute symlink traversal to non-fp mounts

Mateusz Guzik mjg at FreeBSD.org
Wed May 19 15:53:41 UTC 2021


The branch stable/13 has been updated by mjg:

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

commit b3e8bfd771b4b172a4f3619da25b79459e46ba41
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-05-11 03:48:08 +0000
Commit:     Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-05-19 15:53:34 +0000

    cache: fix lockless absolute symlink traversal to non-fp mounts
    
    Said lookups would incorrectly fail with EOPNOTSUP.
    
    Reported by:    kib
    
    (cherry picked from commit 12288bd999ca3a493b8dc4cba109e5a8fa838c45)
---
 sys/kern/vfs_cache.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 8819ef483af5..31d6668a3565 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -3936,6 +3936,7 @@ struct cache_fpl {
 #endif
 };
 
+static bool cache_fplookup_mp_supported(struct mount *mp);
 static bool cache_fplookup_is_mp(struct cache_fpl *fpl);
 static int cache_fplookup_cross_mount(struct cache_fpl *fpl);
 static int cache_fplookup_partial_setup(struct cache_fpl *fpl);
@@ -5174,6 +5175,19 @@ cache_fplookup_symlink(struct cache_fpl *fpl)
 		if (seqc_in_modify(fpl->dvp_seqc)) {
 			return (cache_fpl_aborted(fpl));
 		}
+		/*
+		 * The main loop assumes that ->dvp points to a vnode belonging
+		 * to a filesystem which can do lockless lookup, but the absolute
+		 * symlink can be wandering off to one which does not.
+		 */
+		mp = atomic_load_ptr(&fpl->dvp->v_mount);
+		if (__predict_false(mp == NULL)) {
+			return (cache_fpl_aborted(fpl));
+		}
+		if (!cache_fplookup_mp_supported(mp)) {
+			cache_fpl_checkpoint(fpl);
+			return (cache_fpl_partial(fpl));
+		}
 	}
 	return (0);
 }


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