From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-co1nam03on0096.outbound.protection.outlook.com ([104.47.40.96]:44736 "EHLO NAM03-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727773AbeH3WMR (ORCPT ); Thu, 30 Aug 2018 18:12:17 -0400 From: Sasha Levin To: "stable@vger.kernel.org" CC: Qu Wenruo , David Sterba , Sasha Levin Subject: [PATCH AUTOSEL 4.18 108/113] btrfs: relocation: Only remove reloc rb_trees if reloc control has been initialized Date: Thu, 30 Aug 2018 18:08:34 +0000 Message-ID: <20180830180714.36167-42-alexander.levin@microsoft.com> References: <20180830180714.36167-1-alexander.levin@microsoft.com> In-Reply-To: <20180830180714.36167-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Qu Wenruo [ Upstream commit 389305b2aa68723c754f88d9dbd268a400e10664 ] Invalid reloc tree can cause kernel NULL pointer dereference when btrfs does some cleanup of the reloc roots. It turns out that fs_info::reloc_ctl can be NULL in btrfs_recover_relocation() as we allocate relocation control after all reloc roots have been verified. So when we hit: note, we haven't called set_reloc_control() thus fs_info::reloc_ctl is still NULL. Link: https://bugzilla.kernel.org/show_bug.cgi?id=3D199833 Reported-by: Xu Wen Signed-off-by: Qu Wenruo Tested-by: Gu Jinxiang Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/relocation.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 879b76fa881a..be94c65bb4d2 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1321,18 +1321,19 @@ static void __del_reloc_root(struct btrfs_root *roo= t) struct mapping_node *node =3D NULL; struct reloc_control *rc =3D fs_info->reloc_ctl; =20 - spin_lock(&rc->reloc_root_tree.lock); - rb_node =3D tree_search(&rc->reloc_root_tree.rb_root, - root->node->start); - if (rb_node) { - node =3D rb_entry(rb_node, struct mapping_node, rb_node); - rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); + if (rc) { + spin_lock(&rc->reloc_root_tree.lock); + rb_node =3D tree_search(&rc->reloc_root_tree.rb_root, + root->node->start); + if (rb_node) { + node =3D rb_entry(rb_node, struct mapping_node, rb_node); + rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); + } + spin_unlock(&rc->reloc_root_tree.lock); + if (!node) + return; + BUG_ON((struct btrfs_root *)node->data !=3D root); } - spin_unlock(&rc->reloc_root_tree.lock); - - if (!node) - return; - BUG_ON((struct btrfs_root *)node->data !=3D root); =20 spin_lock(&fs_info->trans_lock); list_del_init(&root->root_list); --=20 2.17.1