lkml.org 
[lkml]   [2018]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.18 136/197] btrfs: relocation: Only remove reloc rb_trees if reloc control has been initialized
    Date
    4.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Qu Wenruo <wqu@suse.com>

    [ 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=199833
    Reported-by: Xu Wen <wen.xu@gatech.edu>
    Signed-off-by: Qu Wenruo <wqu@suse.com>
    Tested-by: Gu Jinxiang <gujx@cn.fujitsu.com>
    Reviewed-by: David Sterba <dsterba@suse.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/btrfs/relocation.c | 23 ++++++++++++-----------
    1 file changed, 12 insertions(+), 11 deletions(-)

    --- a/fs/btrfs/relocation.c
    +++ b/fs/btrfs/relocation.c
    @@ -1321,18 +1321,19 @@ static void __del_reloc_root(struct btrf
    struct mapping_node *node = NULL;
    struct reloc_control *rc = fs_info->reloc_ctl;

    - spin_lock(&rc->reloc_root_tree.lock);
    - rb_node = tree_search(&rc->reloc_root_tree.rb_root,
    - root->node->start);
    - if (rb_node) {
    - node = 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 = tree_search(&rc->reloc_root_tree.rb_root,
    + root->node->start);
    + if (rb_node) {
    + node = 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 != root);
    }
    - spin_unlock(&rc->reloc_root_tree.lock);
    -
    - if (!node)
    - return;
    - BUG_ON((struct btrfs_root *)node->data != root);

    spin_lock(&fs_info->trans_lock);
    list_del_init(&root->root_list);

    \
     
     \ /
      Last update: 2018-09-13 16:02    [W:4.143 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site