On Tue, May 21, 2019 at 07:28:08PM +0800, Qu Wenruo wrote:
> [BUG]
> When mounting a fs with reloc tree and has qgroup enabled, it can cause
> NULL pointer dereference at mount time:
> BUG: kernel NULL pointer dereference, address: 00000000000000a8
> #PF: supervisor read access in kernel mode
> #PF: error_code(0x0000) - not-present page
> PGD 0 P4D 0
> Oops: 0000 [#1] PREEMPT SMP NOPTI
> RIP: 0010:btrfs_qgroup_add_swapped_blocks+0x186/0x300 [btrfs]
> Call Trace:
> replace_path.isra.23+0x685/0x900 [btrfs]
> merge_reloc_root+0x26e/0x5f0 [btrfs]
> merge_reloc_roots+0x10a/0x1a0 [btrfs]
> btrfs_recover_relocation+0x3cd/0x420 [btrfs]
> open_ctree+0x1bc8/0x1ed0 [btrfs]
> btrfs_mount_root+0x544/0x680 [btrfs]
> legacy_get_tree+0x34/0x60
> vfs_get_tree+0x2d/0xf0
> fc_mount+0x12/0x40
> vfs_kern_mount.part.12+0x61/0xa0
> vfs_kern_mount+0x13/0x20
> btrfs_mount+0x16f/0x860 [btrfs]
> legacy_get_tree+0x34/0x60
> vfs_get_tree+0x2d/0xf0
> do_mount+0x81f/0xac0
> ksys_mount+0xbf/0xe0
> __x64_sys_mount+0x25/0x30
> do_syscall_64+0x65/0x240
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> [CAUSE]
> In btrfs_recover_relocation(), we don't have enough info to determine
> which block group we're relocating, but only to merge existing reloc
> trees.
>
> Thus in btrfs_recover_relocation(), rc->block_group is NULL.
> btrfs_qgroup_add_swapped_blocks() hasn't take this into consideration,
> and causes NULL pointer dereference.
>
> The bug is introduced by commit 3d0174f78e72 ("btrfs: qgroup: Only trace
> data extents in leaves if we're relocating data block group"), and
> later qgroup refactor still keeps this optimization.
>
> [FIX]
> Thankfully in the context of btrfs_recover_relocation(), there is no
> other progress can modify tree blocks, thus those swapped tree blocks
> pair will never affect qgroup numbers, no matter whatever we set for
> block->trace_leaf.
>
> So we only need to check if @bg is NULL before accessing @bg->flags.
>
> Reported-by: Juan Erbes <jerbes@xxxxxxxxx>
> Link: https://bugzilla.opensuse.org/show_bug.cgi?id=1134806
> Fixes: 3d0174f78e72 ("btrfs: qgroup: Only trace data extents in leaves if we're relocating data block group")
> Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
I've changed the subject to "btrfs: qgroup: Check bg while resuming
relocation to avoid NULL pointer dereference", patch is going to 5.2-rc
and will be tagged for stable.