btrfs-progs: print-tree: Avoid segfault for heavily corrupted item pointers

Normally corrupted leaf should be caught by csum check, but sometimes
corrupted item pointers (out of leaf range) can still pass csum check.
In fact, our fsck/005 test case image has such corrupted item pointer
and btrfs check can surprisingly fix it.

Anyway, make print-tree to skip such item and remaining slots to avoid
segfault.

Please note that, in btrfs-progs we can't put such check into
check_tree_block() nor do kernel level comprehensive check as under
certain case, btrfs-progs can handle or even repair it.
A strict check_tree_block() or backporting kernel btrfs_check_leaf()
could break such test cases and reduce the utility of btrfs-progs.

Issue: #128
Reported-by: Hubert Kario <hubert@kario.pl>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2018-05-07 15:46:27 +08:00 committed by David Sterba
parent 8a7b9c9b47
commit 9e061cae19
1 changed files with 18 additions and 0 deletions

View File

@ -1179,6 +1179,7 @@ void btrfs_print_leaf(struct extent_buffer *eb)
struct btrfs_item *item;
struct btrfs_disk_key disk_key;
char flags_str[128];
u32 leaf_data_size = BTRFS_LEAF_DATA_SIZE(fs_info);
u32 i;
u32 nr;
u64 flags;
@ -1207,6 +1208,23 @@ void btrfs_print_leaf(struct extent_buffer *eb)
u32 type;
u64 offset;
/*
* Extra check on item pointers
* Here we don't need to be as strict as kernel leaf check.
* Only need to ensure all pointers are pointing range inside
* the leaf, thus no segfault.
*/
if (btrfs_item_offset_nr(eb, i) > leaf_data_size ||
btrfs_item_size_nr(eb, i) + btrfs_item_offset_nr(eb, i) >
leaf_data_size) {
error(
"leaf %llu slot %u pointer invalid, offset %u size %u leaf data limit %u",
btrfs_header_bytenr(eb), i,
btrfs_item_offset_nr(eb, i),
btrfs_item_size_nr(eb, i), leaf_data_size);
error("skip remaining slots");
break;
}
item = btrfs_item_nr(i);
item_size = btrfs_item_size(eb, item);
/* Untyped extraction of slot from btrfs_item_ptr */