Skip to content

Commit c541dce

Browse files
jankarabrauner
authored andcommitted
fs: Protect reconfiguration of sb read-write from racing writes
The reconfigure / remount code takes a lot of effort to protect filesystem's reconfiguration code from racing writes on remounting read-only. However during remounting read-only filesystem to read-write mode userspace writes can start immediately once we clear SB_RDONLY flag. This is inconvenient for example for ext4 because we need to do some writes to the filesystem (such as preparation of quota files) before we can take userspace writes so we are clearing SB_RDONLY flag before we are fully ready to accept userpace writes and syzbot has found a way to exploit this [1]. Also as far as I'm reading the code the filesystem remount code was protected from racing writes in the legacy mount path by the mount's MNT_READONLY flag so this is relatively new problem. It is actually fairly easy to protect remount read-write from racing writes using sb->s_readonly_remount flag so let's just do that instead of having to workaround these races in the filesystem code. [1] https://lore.kernel.org/all/[email protected]/T/ Signed-off-by: Jan Kara <[email protected]> Message-Id: <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 2d8c9dc commit c541dce

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

fs/super.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ int reconfigure_super(struct fs_context *fc)
903903
struct super_block *sb = fc->root->d_sb;
904904
int retval;
905905
bool remount_ro = false;
906+
bool remount_rw = false;
906907
bool force = fc->sb_flags & SB_FORCE;
907908

908909
if (fc->sb_flags_mask & ~MS_RMT_MASK)
@@ -920,7 +921,7 @@ int reconfigure_super(struct fs_context *fc)
920921
bdev_read_only(sb->s_bdev))
921922
return -EACCES;
922923
#endif
923-
924+
remount_rw = !(fc->sb_flags & SB_RDONLY) && sb_rdonly(sb);
924925
remount_ro = (fc->sb_flags & SB_RDONLY) && !sb_rdonly(sb);
925926
}
926927

@@ -950,6 +951,14 @@ int reconfigure_super(struct fs_context *fc)
950951
if (retval)
951952
return retval;
952953
}
954+
} else if (remount_rw) {
955+
/*
956+
* We set s_readonly_remount here to protect filesystem's
957+
* reconfigure code from writes from userspace until
958+
* reconfigure finishes.
959+
*/
960+
sb->s_readonly_remount = 1;
961+
smp_wmb();
953962
}
954963

955964
if (fc->ops->reconfigure) {

0 commit comments

Comments
 (0)