lkml.org 
[lkml]   [2019]   [Jan]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 08/51] Btrfs: check btree nodes nritems
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Liu Bo <bo.li.liu@oracle.com>

    commit 053ab70f0604224c7893b43f9d9d5efa283580d6 upstream.

    When btree node (level = 1) has nritems which equals to zero,
    we can end up with panic due to insert_ptr()'s

    BUG_ON(slot > nritems);

    where slot is 1 and nritems is 0, as copy_for_split() calls
    insert_ptr(.., path->slots[1] + 1, ...);

    A invalid value results in the whole mess, this adds the check
    for btree's node nritems so that we stop reading block when
    when something is wrong.

    Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
    Reviewed-by: David Sterba <dsterba@suse.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
    Signed-off-by: Chris Mason <clm@fb.com>
    Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/btrfs/disk-io.c | 16 ++++++++++++++++
    1 file changed, 16 insertions(+)

    --- a/fs/btrfs/disk-io.c
    +++ b/fs/btrfs/disk-io.c
    @@ -609,6 +609,19 @@ static noinline int check_leaf(struct bt
    return 0;
    }

    +static int check_node(struct btrfs_root *root, struct extent_buffer *node)
    +{
    + unsigned long nr = btrfs_header_nritems(node);
    +
    + if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
    + btrfs_crit(root->fs_info,
    + "corrupt node: block %llu root %llu nritems %lu",
    + node->start, root->objectid, nr);
    + return -EIO;
    + }
    + return 0;
    +}
    +
    static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
    u64 phy_offset, struct page *page,
    u64 start, u64 end, int mirror)
    @@ -680,6 +693,9 @@ static int btree_readpage_end_io_hook(st
    ret = -EIO;
    }

    + if (found_level > 0 && check_node(root, eb))
    + ret = -EIO;
    +
    if (!ret)
    set_extent_buffer_uptodate(eb);
    err:

    \
     
     \ /
      Last update: 2019-01-15 18:02    [W:2.182 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site