From: David Sterba <dsterba@suse.cz>
To: Anand Jain <anand.jain@oracle.com>
Cc: linux-btrfs@vger.kernel.org, dsterba@suse.com,
josef@toxicpanda.com,
syzbot+4cfe71a4da060be47502@syzkaller.appspotmail.com
Subject: Re: [PATCH RESEND v2] btrfs: fix devid 0 without a replace item by failing the mount
Date: Tue, 3 Nov 2020 19:36:18 +0100 [thread overview]
Message-ID: <20201103183618.GA6756@twin.jikos.cz> (raw)
In-Reply-To: <d0b5790792b8b826504dd239ad9efc514f3d9109.1604009248.git.anand.jain@oracle.com>
On Fri, Oct 30, 2020 at 06:53:56AM +0800, Anand Jain wrote:
> If there is a BTRFS_DEV_REPLACE_DEVID without a replace item, then
> it means some device is trying to attack or may be corrupted. Fail the
> mount so that the user can remove the attacking or fix the corrupted
> device.
>
> As of now if BTRFS_DEV_REPLACE_DEVID is present without the replace
> item, in __btrfs_free_extra_devids() we determine that there is an
> extra device, and free those extra devices but continue to mount the
> device.
> However, we were wrong in keeping tack of the rw_devices so the syzbot
> testcase failed as below [1].
>
> [1]
> WARNING: CPU: 1 PID: 3612 at fs/btrfs/volumes.c:1166 close_fs_devices.part.0+0x607/0x800 fs/btrfs/volumes.c:1166
> Kernel panic - not syncing: panic_on_warn set ...
> CPU: 1 PID: 3612 Comm: syz-executor.2 Not tainted 5.9.0-rc4-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> Call Trace:
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0x198/0x1fd lib/dump_stack.c:118
> panic+0x347/0x7c0 kernel/panic.c:231
> __warn.cold+0x20/0x46 kernel/panic.c:600
> report_bug+0x1bd/0x210 lib/bug.c:198
> handle_bug+0x38/0x90 arch/x86/kernel/traps.c:234
> exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254
> asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536
> RIP: 0010:close_fs_devices.part.0+0x607/0x800 fs/btrfs/volumes.c:1166
> Code: 0f b6 04 02 84 c0 74 02 7e 33 48 8b 44 24 18 c6 80 30 01 00 00 00 48 83 c4 30 5b 5d 41 5c 41 5d 41 5e 41 5f c3 e8 99 ce 6a fe <0f> 0b e9 71 ff ff ff e8 8d ce 6a fe 0f 0b e9 20 ff ff ff e8 d1 d5
Unless we need the Code: line to understand what happend, you can remove
it from the changelog
> RSP: 0018:ffffc900091777e0 EFLAGS: 00010246
> RAX: 0000000000040000 RBX: ffffffffffffffff RCX: ffffc9000c8b7000
> RDX: 0000000000040000 RSI: ffffffff83097f47 RDI: 0000000000000007
> RBP: dffffc0000000000 R08: 0000000000000001 R09: ffff8880988a187f
> R10: 0000000000000000 R11: 0000000000000001 R12: ffff88809593a130
> R13: ffff88809593a1ec R14: ffff8880988a1908 R15: ffff88809593a050
> close_fs_devices fs/btrfs/volumes.c:1193 [inline]
> btrfs_close_devices+0x95/0x1f0 fs/btrfs/volumes.c:1179
> open_ctree+0x4984/0x4a2d fs/btrfs/disk-io.c:3434
> btrfs_fill_super fs/btrfs/super.c:1316 [inline]
> btrfs_mount_root.cold+0x14/0x165 fs/btrfs/super.c:1672
>
> The fix here is, when we determine that there isn't a replace item
> then fail the mount if there is a replace target device (devid 0).
>
> Cc: josef@toxicpanda.com
> Reported-by: syzbot+4cfe71a4da060be47502@syzkaller.appspotmail.com
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
> Depends on the patches
> btrfs: drop never met condition of disk_total_bytes == 0
> btrfs: fix btrfs_find_device unused arg seed
As this is a fix that could go to the master, the cleanups should
follow.
> If these patches aren't integrated yet, then please add the last arg in
> the function btrfs_find_device(). Any value is fine as it doesn't care.
Ok, fixed.
> fstest case will follow.
>
> v2: changed title
> old: btrfs: fix rw_devices count in __btrfs_free_extra_devids
>
> In btrfs_init_dev_replace() try to match the presence of replace_item
> to the BTRFS_DEV_REPLACE_DEVID device. If fails then fail the
> mount. So drop the similar check in __btrfs_free_extra_devids().
>
> fs/btrfs/dev-replace.c | 26 ++++++++++++++++++++++++--
> fs/btrfs/volumes.c | 26 +++++++-------------------
> 2 files changed, 31 insertions(+), 21 deletions(-)
>
> diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
> index ffab2758f991..8b3935757dc1 100644
> --- a/fs/btrfs/dev-replace.c
> +++ b/fs/btrfs/dev-replace.c
> @@ -91,6 +91,17 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
> ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
> if (ret) {
> no_valid_dev_replace_entry_found:
> + /*
> + * We don't have a replace item or it's corrupted.
> + * If there is a replace target, fail the mount.
> + */
> + if (btrfs_find_device(fs_info->fs_devices,
> + BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
> + btrfs_err(fs_info,
> + "found replace target device without a replace item");
> + ret = -EIO;
This IMHO qualifies as a corruption so it should be EUCLEAN. The rest of
the function used EIO for error state but the code is from 2012 and we
used EIO instead.
> + goto out;
> + }
> ret = 0;
> dev_replace->replace_state =
> BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
> @@ -143,8 +154,19 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
> case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
> case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
> case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
> - dev_replace->srcdev = NULL;
> - dev_replace->tgtdev = NULL;
> + /*
> + * We don't have an active replace item but if there is a
> + * replace target, fail the mount.
> + */
> + if (btrfs_find_device(fs_info->fs_devices,
> + BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
> + btrfs_err(fs_info,
> + "replace devid present without an active replace item");
> + ret = -EIO;
Same here.
> + } else {
> + dev_replace->srcdev = NULL;
> + dev_replace->tgtdev = NULL;
> + }
> break;
> case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
> case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 1b2742da5d4a..bb6f067f2fb9 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -1056,22 +1056,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
> continue;
> }
>
> - if (device->devid == BTRFS_DEV_REPLACE_DEVID) {
> - /*
> - * In the first step, keep the device which has
> - * the correct fsid and the devid that is used
> - * for the dev_replace procedure.
> - * In the second step, the dev_replace state is
> - * read from the device tree and it is known
> - * whether the procedure is really active or
> - * not, which means whether this device is
> - * used or whether it should be removed.
> - */
> - if (step == 0 || test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
This removes the use of step parameter so it can be removed from the
call chain too (separate patch).
Patch added to misc-next, thanks.
next prev parent reply other threads:[~2020-11-03 18:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-29 22:53 [PATCH 0/1] handle attacking device with devid=0 Anand Jain
2020-10-29 22:53 ` [PATCH RESEND v2] btrfs: fix devid 0 without a replace item by failing the mount Anand Jain
2020-11-03 18:36 ` David Sterba [this message]
2020-11-04 0:55 ` Anand Jain
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201103183618.GA6756@twin.jikos.cz \
--to=dsterba@suse.cz \
--cc=anand.jain@oracle.com \
--cc=dsterba@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=syzbot+4cfe71a4da060be47502@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).