diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2021-01-26 22:14:49 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2021-02-01 12:39:18 +0000 |
commit | 6a3047840dfbbdb59d96a325f295f42755648545 (patch) | |
tree | f3a7d5913b79e903e5f1ea58ccd4f40551da6049 | |
parent | be03df57d62f4cc6161349f9127309ea20395c0d (diff) | |
download | src-6a3047840dfbbdb59d96a325f295f42755648545.tar.gz src-6a3047840dfbbdb59d96a325f295f42755648545.zip |
cache: handle NOFOLLOW requests for symlinks
Tested by: pho
(cherry picked from commit 8cbd164a179c182e8fd4a71f366bc48fe840eafb)
-rw-r--r-- | sys/kern/vfs_cache.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index ff8aad14001b..b8b876657211 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -4307,11 +4307,22 @@ cache_fplookup_final_modifying(struct cache_fpl *fpl) } /* - * Check if the target is either a symlink or a mount point. - * Since we expect this to be the terminal vnode it should - * almost never be true. + * If they want the symlink itself we are fine, but if they want to + * follow it regular lookup has to be engaged. */ - if (__predict_false(tvp->v_type == VLNK || cache_fplookup_is_mp(fpl))) { + if (tvp->v_type == VLNK) { + if ((cnp->cn_flags & FOLLOW) != 0) { + vput(dvp); + vput(tvp); + return (cache_fpl_aborted(fpl)); + } + } + + /* + * Since we expect this to be the terminal vnode it should almost never + * be a mount point. + */ + if (__predict_false(cache_fplookup_is_mp(fpl))) { vput(dvp); vput(tvp); return (cache_fpl_aborted(fpl)); @@ -4614,7 +4625,15 @@ cache_fplookup_noentry(struct cache_fpl *fpl) return (cache_fpl_handled(fpl)); } - if (__predict_false(tvp->v_type == VLNK || cache_fplookup_is_mp(fpl))) { + if (tvp->v_type == VLNK) { + if ((cnp->cn_flags & FOLLOW) != 0) { + vput(dvp); + vput(tvp); + return (cache_fpl_aborted(fpl)); + } + } + + if (__predict_false(cache_fplookup_is_mp(fpl))) { vput(dvp); vput(tvp); return (cache_fpl_aborted(fpl)); |