summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2022-07-05 00:26:29 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-08-21 16:16:15 +0300
commitbc8c5b3b3eb9235e26bc31ceef617182c0da41e5 (patch)
treeb0dc05aac70db385e673df4313f054b28d1f2277 /fs
parentbda7046d4d59a2224a689ed0129ef152a6761cf6 (diff)
downloadlinux-bc8c5b3b3eb9235e26bc31ceef617182c0da41e5.tar.xz
__follow_mount_rcu(): verify that mount_lock remains unchanged
commit 20aac6c60981f5bfacd66661d090d907bf1482f0 upstream. Validate mount_lock seqcount as soon as we cross into mount in RCU mode. Sure, ->mnt_root is pinned and will remain so until we do rcu_read_unlock() anyway, and we will eventually fail to unlazy if the mount_lock had been touched, but we might run into a hard error (e.g. -ENOENT) before trying to unlazy. And it's possible to end up with RCU pathwalk racing with rename() and umount() in a way that would fail with -ENOENT while non-RCU pathwalk would've succeeded with any timings. Once upon a time we hadn't needed that, but analysis had been subtle, brittle and went out of window as soon as RENAME_EXCHANGE had been added. It's narrow, hard to hit and won't get you anything other than stray -ENOENT that could be arranged in much easier way with the same priveleges, but it's a bug all the same. Cc: stable@kernel.org X-sky-is-falling: unlikely Fixes: da1ce0670c14 "vfs: add cross-rename" Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 96491f092a99..eba2f13d229d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1348,6 +1348,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
* becoming unpinned.
*/
flags = dentry->d_flags;
+ if (read_seqretry(&mount_lock, nd->m_seq))
+ return false;
continue;
}
if (read_seqretry(&mount_lock, nd->m_seq))