Skip to content

Commit 0014eda

Browse files
committed
fs: unset MNT_WRITE_HOLD on failure
After mnt_hold_writers() has been called we will always have set MNT_WRITE_HOLD and consequently we always need to pair mnt_hold_writers() with mnt_unhold_writers(). After the recent cleanup in [1] where Al switched from a do-while to a for loop the cleanup currently fails to unset MNT_WRITE_HOLD for the first mount that was changed. Fix this and make sure that the first mount will be cleaned up and add some comments to make it more obvious. Link: https://lore.kernel.org/lkml/0000000000007cc21d05dd0432b8@google.com Link: https://lore.kernel.org/lkml/00000000000080e10e05dd043247@google.com Link: https://lore.kernel.org/r/20220420131925.2464685-1-brauner@kernel.org Fixes: e257039 ("mount_setattr(): clean the control flow and calling conventions") [1] Cc: Hillf Danton <hdanton@sina.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Reported-by: syzbot+10a16d1c43580983f6a2@syzkaller.appspotmail.com Reported-by: syzbot+306090cfa3294f0bbfb3@syzkaller.appspotmail.com Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
1 parent b2d229d commit 0014eda

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

fs/namespace.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4058,10 +4058,22 @@ static int mount_setattr_prepare(struct mount_kattr *kattr, struct mount *mnt)
40584058
if (err) {
40594059
struct mount *p;
40604060

4061-
for (p = mnt; p != m; p = next_mnt(p, mnt)) {
4061+
/*
4062+
* If we had to call mnt_hold_writers() MNT_WRITE_HOLD will
4063+
* be set in @mnt_flags. The loop unsets MNT_WRITE_HOLD for all
4064+
* mounts and needs to take care to include the first mount.
4065+
*/
4066+
for (p = mnt; p; p = next_mnt(p, mnt)) {
40624067
/* If we had to hold writers unblock them. */
40634068
if (p->mnt.mnt_flags & MNT_WRITE_HOLD)
40644069
mnt_unhold_writers(p);
4070+
4071+
/*
4072+
* We're done once the first mount we changed got
4073+
* MNT_WRITE_HOLD unset.
4074+
*/
4075+
if (p == m)
4076+
break;
40654077
}
40664078
}
40674079
return err;

0 commit comments

Comments
 (0)