Konstantin Demin
8cbaf1dea2
3rd patchs (in alphabetical order): - bbr3 - ntsync5 - openwrt - pf-kernel - xanmod - zen no configuration changes for now
102 lines
4.2 KiB
Diff
102 lines
4.2 KiB
Diff
From 7f83049bda761f340991af8dce79a4e98c62b378 Mon Sep 17 00:00:00 2001
|
|
From: Qu Wenruo <wqu@suse.com>
|
|
Date: Thu, 19 Sep 2024 20:18:11 +0930
|
|
Subject: btrfs: reject ro->rw reconfiguration if there are hard ro
|
|
requirements
|
|
|
|
[BUG]
|
|
Syzbot reports the following crash:
|
|
|
|
BTRFS info (device loop0 state MCS): disabling free space tree
|
|
BTRFS info (device loop0 state MCS): clearing compat-ro feature flag for FREE_SPACE_TREE (0x1)
|
|
BTRFS info (device loop0 state MCS): clearing compat-ro feature flag for FREE_SPACE_TREE_VALID (0x2)
|
|
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000003: 0000 [#1] PREEMPT SMP KASAN NOPTI
|
|
KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
|
|
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
|
|
RIP: 0010:backup_super_roots fs/btrfs/disk-io.c:1691 [inline]
|
|
RIP: 0010:write_all_supers+0x97a/0x40f0 fs/btrfs/disk-io.c:4041
|
|
Call Trace:
|
|
<TASK>
|
|
btrfs_commit_transaction+0x1eae/0x3740 fs/btrfs/transaction.c:2530
|
|
btrfs_delete_free_space_tree+0x383/0x730 fs/btrfs/free-space-tree.c:1312
|
|
btrfs_start_pre_rw_mount+0xf28/0x1300 fs/btrfs/disk-io.c:3012
|
|
btrfs_remount_rw fs/btrfs/super.c:1309 [inline]
|
|
btrfs_reconfigure+0xae6/0x2d40 fs/btrfs/super.c:1534
|
|
btrfs_reconfigure_for_mount fs/btrfs/super.c:2020 [inline]
|
|
btrfs_get_tree_subvol fs/btrfs/super.c:2079 [inline]
|
|
btrfs_get_tree+0x918/0x1920 fs/btrfs/super.c:2115
|
|
vfs_get_tree+0x90/0x2b0 fs/super.c:1800
|
|
do_new_mount+0x2be/0xb40 fs/namespace.c:3472
|
|
do_mount fs/namespace.c:3812 [inline]
|
|
__do_sys_mount fs/namespace.c:4020 [inline]
|
|
__se_sys_mount+0x2d6/0x3c0 fs/namespace.c:3997
|
|
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
|
|
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
|
|
entry_SYSCALL_64_after_hwframe+0x77/0x7f
|
|
|
|
[CAUSE]
|
|
To support mounting different subvolume with different RO/RW flags for
|
|
the new mount APIs, btrfs introduced two workaround to support this feature:
|
|
|
|
- Skip mount option/feature checks if we are mounting a different
|
|
subvolume
|
|
|
|
- Reconfigure the fs to RW if the initial mount is RO
|
|
|
|
Combining these two, we can have the following sequence:
|
|
|
|
- Mount the fs ro,rescue=all,clear_cache,space_cache=v1
|
|
rescue=all will mark the fs as hard read-only, so no v2 cache clearing
|
|
will happen.
|
|
|
|
- Mount a subvolume rw of the same fs.
|
|
We go into btrfs_get_tree_subvol(), but fc_mount() returns EBUSY
|
|
because our new fc is RW, different from the original fs.
|
|
|
|
Now we enter btrfs_reconfigure_for_mount(), which switches the RO flag
|
|
first so that we can grab the existing fs_info.
|
|
Then we reconfigure the fs to RW.
|
|
|
|
- During reconfiguration, option/features check is skipped
|
|
This means we will restart the v2 cache clearing, and convert back to
|
|
v1 cache.
|
|
This will trigger fs writes, and since the original fs has "rescue=all"
|
|
option, it skips the csum tree read.
|
|
|
|
And eventually causing NULL pointer dereference in super block
|
|
writeback.
|
|
|
|
[FIX]
|
|
For reconfiguration caused by different subvolume RO/RW flags, ensure we
|
|
always run btrfs_check_options() to ensure we have proper hard RO
|
|
requirements met.
|
|
|
|
In fact the function btrfs_check_options() doesn't really do many
|
|
complex checks, but hard RO requirement and some feature dependency
|
|
checks, thus there is no special reason not to do the check for mount
|
|
reconfiguration.
|
|
|
|
Reported-by: syzbot+56360f93efa90ff15870@syzkaller.appspotmail.com
|
|
Link: https://lore.kernel.org/linux-btrfs/0000000000008c5d090621cb2770@google.com/
|
|
Fixes: f044b318675f ("btrfs: handle the ro->rw transition for mounting different subvolumes")
|
|
CC: stable@vger.kernel.org # 6.8+
|
|
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
|
|
Signed-off-by: Qu Wenruo <wqu@suse.com>
|
|
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
---
|
|
fs/btrfs/super.c | 3 +--
|
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
|
|
--- a/fs/btrfs/super.c
|
|
+++ b/fs/btrfs/super.c
|
|
@@ -1519,8 +1519,7 @@ static int btrfs_reconfigure(struct fs_c
|
|
sync_filesystem(sb);
|
|
set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
|
|
|
|
- if (!mount_reconfigure &&
|
|
- !btrfs_check_options(fs_info, &ctx->mount_opt, fc->sb_flags))
|
|
+ if (!btrfs_check_options(fs_info, &ctx->mount_opt, fc->sb_flags))
|
|
return -EINVAL;
|
|
|
|
ret = btrfs_check_features(fs_info, !(fc->sb_flags & SB_RDONLY));
|