diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2025-04-28 23:56:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-05-18 08:21:25 +0200 |
commit | 0e42a14899ca8982d20599965c7b5704be27f67f (patch) | |
tree | 31efd1ba408a2f14f215ee73ca380d12c890f31b | |
parent | 8642cbf11eeff6a60049e4dd6e3f4cab61625d8f (diff) |
do_umount(): add missing barrier before refcount checks in sync case
[ Upstream commit 65781e19dcfcb4aed1167d87a3ffcc2a0c071d47 ]
do_umount() analogue of the race fixed in 119e1ef80ecf "fix
__legitimize_mnt()/mntput() race". Here we want to make sure that
if __legitimize_mnt() doesn't notice our lock_mount_hash(), we will
notice their refcount increment. Harder to hit than mntput_no_expire()
one, fortunately, and consequences are milder (sync umount acting
like umount -l on a rare race with RCU pathwalk hitting at just the
wrong time instead of use-after-free galore mntput_no_expire()
counterpart used to be hit). Still a bug...
Fixes: 48a066e72d97 ("RCU'd vfsmounts")
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | fs/namespace.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 57166cc7e511..0dcd57a75ad4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -629,7 +629,7 @@ int __legitimize_mnt(struct vfsmount *bastard, unsigned seq) return 0; mnt = real_mount(bastard); mnt_add_count(mnt, 1); - smp_mb(); // see mntput_no_expire() + smp_mb(); // see mntput_no_expire() and do_umount() if (likely(!read_seqretry(&mount_lock, seq))) return 0; if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { @@ -1707,6 +1707,7 @@ static int do_umount(struct mount *mnt, int flags) umount_tree(mnt, UMOUNT_PROPAGATE); retval = 0; } else { + smp_mb(); // paired with __legitimize_mnt() shrink_submounts(mnt); retval = -EBUSY; if (!propagate_mount_busy(mnt, 2)) { |