Re: [PATCH] fs: Protect reconfiguration of sb read-write from racing writes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 15, 2023 at 01:38:48PM +0200, Jan Kara wrote:
> 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/00000000000006a0df05f6667499@xxxxxxxxxx/T/
> Signed-off-by: Jan Kara <jack@xxxxxxx>
> ---
>  fs/super.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/super.c b/fs/super.c
> index 34afe411cf2b..6cd64961aa07 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -903,6 +903,7 @@ int reconfigure_super(struct fs_context *fc)
>  	struct super_block *sb = fc->root->d_sb;
>  	int retval;
>  	bool remount_ro = false;
> +	bool remount_rw = false;
>  	bool force = fc->sb_flags & SB_FORCE;
>  
>  	if (fc->sb_flags_mask & ~MS_RMT_MASK)
> @@ -920,7 +921,7 @@ int reconfigure_super(struct fs_context *fc)
>  		    bdev_read_only(sb->s_bdev))
>  			return -EACCES;
>  #endif
> -
> +		remount_rw = !(fc->sb_flags & SB_RDONLY) && sb_rdonly(sb);
>  		remount_ro = (fc->sb_flags & SB_RDONLY) && !sb_rdonly(sb);
>  	}
>  
> @@ -950,6 +951,14 @@ int reconfigure_super(struct fs_context *fc)
>  			if (retval)
>  				return retval;
>  		}
> +	} else if (remount_rw) {
> +		/*
> +		 * We set s_readonly_remount here to protect filesystem's
> +		 * reconfigure code from writes from userspace until
> +		 * reconfigure finishes.
> +		 */
> +		sb->s_readonly_remount = 1;
> +		smp_wmb();

What does the magic random memory barrier do? What is it ordering,
and what is it paired with?

This sort of thing is much better done with small helpers that
encapsulate the necessary memory barriers:

sb_set_readonly_remount()
sb_clear_readonly_remount()

alongside the helper that provides the read-side check and memory
barrier the write barrier is associated with.

I don't often ask for code to be cleaned up before a bug fix can be
added, but I think this is one of the important cases where it does
actually matter - we should never add undocumented memory barriers
in the code like this...

Cheers,

Dave.
-- 
Dave Chinner
david@xxxxxxxxxxxxx



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux