Patch "btrfs: fix compat_ro checks against remount" has been added to the 6.0-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    btrfs: fix compat_ro checks against remount

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     btrfs-fix-compat_ro-checks-against-remount.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 2d3eb4ad5a3518fbc0ba08521ced91eb0528fe23
Author: Qu Wenruo <wqu@xxxxxxxx>
Date:   Thu Dec 22 07:59:17 2022 +0800

    btrfs: fix compat_ro checks against remount
    
    [ Upstream commit 2ba48b20049b5a76f34a85f853c9496d1b10533a ]
    
    [BUG]
    Even with commit 81d5d61454c3 ("btrfs: enhance unsupported compat RO
    flags handling"), btrfs can still mount a fs with unsupported compat_ro
    flags read-only, then remount it RW:
    
      # btrfs ins dump-super /dev/loop0 | grep compat_ro_flags -A 3
      compat_ro_flags               0x403
                            ( FREE_SPACE_TREE |
                              FREE_SPACE_TREE_VALID |
                              unknown flag: 0x400 )
    
      # mount /dev/loop0 /mnt/btrfs
      mount: /mnt/btrfs: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
             dmesg(1) may have more information after failed mount system call.
      ^^^ RW mount failed as expected ^^^
    
      # dmesg -t | tail -n5
      loop0: detected capacity change from 0 to 1048576
      BTRFS: device fsid cb5b82f5-0fdd-4d81-9b4b-78533c324afa devid 1 transid 7 /dev/loop0 scanned by mount (1146)
      BTRFS info (device loop0): using crc32c (crc32c-intel) checksum algorithm
      BTRFS info (device loop0): using free space tree
      BTRFS error (device loop0): cannot mount read-write because of unknown compat_ro features (0x403)
      BTRFS error (device loop0): open_ctree failed
    
      # mount /dev/loop0 -o ro /mnt/btrfs
      # mount -o remount,rw /mnt/btrfs
      ^^^ RW remount succeeded unexpectedly ^^^
    
    [CAUSE]
    Currently we use btrfs_check_features() to check compat_ro flags against
    our current mount flags.
    
    That function get reused between open_ctree() and btrfs_remount().
    
    But for btrfs_remount(), the super block we passed in still has the old
    mount flags, thus btrfs_check_features() still believes we're mounting
    read-only.
    
    [FIX]
    Replace the existing @sb argument with @is_rw_mount.
    
    As originally we only use @sb to determine if the mount is RW.
    
    Now it's callers' responsibility to determine if the mount is RW, and
    since there are only two callers, the check is pretty simple:
    
    - caller in open_ctree()
      Just pass !sb_rdonly().
    
    - caller in btrfs_remount()
      Pass !(*flags & SB_RDONLY), as our check should be against the new
      flags.
    
    Now we can correctly reject the RW remount:
    
      # mount /dev/loop0 -o ro /mnt/btrfs
      # mount -o remount,rw /mnt/btrfs
      mount: /mnt/btrfs: mount point not mounted or bad option.
             dmesg(1) may have more information after failed mount system call.
      # dmesg -t | tail -n 1
      BTRFS error (device loop0: state M): cannot mount read-write because of unknown compat_ro features (0x403)
    
    Reported-by: Chung-Chiang Cheng <shepjeng@xxxxxxxxx>
    Fixes: 81d5d61454c3 ("btrfs: enhance unsupported compat RO flags handling")
    CC: stable@xxxxxxxxxxxxxxx # 5.15+
    Reviewed-by: Anand Jain <anand.jain@xxxxxxxxxx>
    Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
    Reviewed-by: David Sterba <dsterba@xxxxxxxx>
    Signed-off-by: David Sterba <dsterba@xxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7834dc77c935..d7a7f6288e70 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3286,6 +3286,8 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
 /*
  * Do various sanity and dependency checks of different features.
  *
+ * @is_rw_mount:	If the mount is read-write.
+ *
  * This is the place for less strict checks (like for subpage or artificial
  * feature dependencies).
  *
@@ -3296,7 +3298,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
  * (space cache related) can modify on-disk format like free space tree and
  * screw up certain feature dependencies.
  */
-int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb)
+int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount)
 {
 	struct btrfs_super_block *disk_super = fs_info->super_copy;
 	u64 incompat = btrfs_super_incompat_flags(disk_super);
@@ -3335,7 +3337,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb)
 	if (btrfs_super_nodesize(disk_super) > PAGE_SIZE)
 		incompat |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;
 
-	if (compat_ro_unsupp && !sb_rdonly(sb)) {
+	if (compat_ro_unsupp && is_rw_mount) {
 		btrfs_err(fs_info,
 	"cannot mount read-write because of unknown compat_ro features (0x%llx)",
 		       compat_ro);
@@ -3538,7 +3540,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
 		goto fail_alloc;
 	}
 
-	ret = btrfs_check_features(fs_info, sb);
+	ret = btrfs_check_features(fs_info, !sb_rdonly(sb));
 	if (ret < 0) {
 		err = ret;
 		goto fail_alloc;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index c67c15d4d20b..6e49979024f0 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -48,7 +48,7 @@ int __cold open_ctree(struct super_block *sb,
 void __cold close_ctree(struct btrfs_fs_info *fs_info);
 int btrfs_validate_super(struct btrfs_fs_info *fs_info,
 			 struct btrfs_super_block *sb, int mirror_num);
-int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb);
+int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount);
 int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors);
 struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev);
 struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index b6f3f24ac95d..64bda2f53311 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2012,7 +2012,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
 	if (ret)
 		goto restore;
 
-	ret = btrfs_check_features(fs_info, sb);
+	ret = btrfs_check_features(fs_info, !(*flags & SB_RDONLY));
 	if (ret < 0)
 		goto restore;
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux