diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2016-06-23 19:32:45 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-07-26 07:52:25 -0400 |
commit | 5e24e9af01abcb151173bb133f1a72b94239c670 (patch) | |
tree | acaaca007c5763a9f6309de02fa4459946132e67 /fs/btrfs | |
parent | 6fb37b756acce6d6e045f79c3764206033f617b4 (diff) |
Btrfs: error out if generic_bin_search get invalid arguments
With btrfs-corrupt-block, one can set btree node/leaf's field, if
we assign a negative value to node/leaf, we can get various hangs,
eg. if extent_root's nritems is -2ULL, then we get stuck in
btrfs_read_block_groups() because it has a while loop and
btrfs_search_slot() on extent_root will always return the first
child.
This lets us know what's happening and returns a EINVAL to callers
instead of returning the first item.
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a85cf7d23309..362879da4f0d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1771,6 +1771,14 @@ static noinline int generic_bin_search(struct extent_buffer *eb, | |||
1771 | unsigned long map_len = 0; | 1771 | unsigned long map_len = 0; |
1772 | int err; | 1772 | int err; |
1773 | 1773 | ||
1774 | if (low > high) { | ||
1775 | btrfs_err(eb->fs_info, | ||
1776 | "%s: low (%d) > high (%d) eb %llu owner %llu level %d", | ||
1777 | __func__, low, high, eb->start, | ||
1778 | btrfs_header_owner(eb), btrfs_header_level(eb)); | ||
1779 | return -EINVAL; | ||
1780 | } | ||
1781 | |||
1774 | while (low < high) { | 1782 | while (low < high) { |
1775 | mid = (low + high) / 2; | 1783 | mid = (low + high) / 2; |
1776 | offset = p + mid * item_size; | 1784 | offset = p + mid * item_size; |