On Tue, Jun 10, 2025 at 09:21:32AM +0100, Al Viro wrote: > Calls of do_umount() are always preceded by can_umount(), where we'd > done a racy check for mount belonging to our namespace; if it wasn't, > can_unmount() would've failed with -EINVAL and we wouldn't have > reached do_umount() at all. > > That check needs to be redone once we have acquired namespace_sem > and in do_umount() we do that. However, that's done in a very odd > way; we check that mount is still in rbtree of _some_ namespace or > its mnt_list is not empty. It is equivalent to check_mnt(mnt) - > we know that earlier mnt was mounted in our namespace; if it has > stayed there, it's going to remain in rbtree of our namespace. > OTOH, if it ever had been removed from out namespace, it would be > removed from rbtree and it never would've re-added to a namespace > afterwards. As for ->mnt_list, for something that had been mounted > in a namespace we'll never observe non-empty ->mnt_list while holding > namespace_sem - it does temporarily become non-empty during > umount_tree(), but that doesn't outlast the call of umount_tree(), > let alone dropping namespace_sem. > > Things get much easier to follow if we replace that with (equivalent) > check_mnt(mnt) there. What's more, currently we treat a failure of > that test as "quietly do nothing"; we might as well pretend that we'd > lost the race and fail on that the same way can_umount() would have. > > Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> > --- Reviewed-by: Christian Brauner <brauner@xxxxxxxxxx>