btrfs-progs: print-tree: Avoid segfault for heavily corrupted item pointers
PATCH 1/2 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 restrict check_tree_block() or backporting kernel btrfs_check_leaf() could break such test cases and reduce the utility of btrfs-progs.
Issue: #128
--- print-tree.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
print-tree.c +18 -0
@@ -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 restrict 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 */
Signature · 1 line
2.17.0
PATCH 2/2 btrfs-progs: misc-tests: Add test case for dump-tree on heavily corrupted leaf
--- .../032-bad-item-ptr/bad_item_ptr.raw.xz | Bin 0 -> 21964 bytes tests/misc-tests/032-bad-item-ptr/test.sh | 17 +++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/misc-tests/032-bad-item-ptr/bad_item_ptr.raw.xz create mode 100755 tests/misc-tests/032-bad-item-ptr/test.sh
tests/misc-tests/032-bad-item-ptr/bad_item_ptr.raw.xz new file binary +0 -0
tests/misc-tests/032-bad-item-ptr/test.sh new file +17 -0
@@ -0,0 +1,17 @@ +#!/bin/bash +# +# Verify that btrfs inspect dump-tree won't segfault on heavily corrupted +# tree leaf +# Issue: #128 + +source "$TEST_TOP/common" + +check_prereq btrfs + +check_image() { + run_check "$TOP/btrfs" inspect dump-tree "$1" + run_mustfail "btrfs check failed to detect such corruption" \ + "$TOP/btrfs" check "$1" +} + +check_all_images
Signature · 1 line
2.17.0
Quoted 8 lines · Qu Wenruo
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.
Quoted 8 lines
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 restrictcheck_tree_block()or backporting kernelbtrfs_check_leaf()could break such test cases and reduce the utility of btrfs-progs.Issue: #128
Reported-by Hubert Kario <[email protected]>
Mail changed to <[email protected]> (Github version already updated.)
Thanks,
Qu
Quoted 42 lines
Signed-off-by Qu Wenruo <[email protected]>--- print-tree.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)print-tree.c +18
-0@@ -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 restrict 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 */
Quoted 17 lines · Qu Wenruo
Quoted 14 lines · Qu Wenruo
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 restrictcheck_tree_block()or backporting kernelbtrfs_check_leaf()could break such test cases and reduce the utility of btrfs-progs.
Quoted 4 lines
Quoted 2 lines
Issue: #128
Reported-by Hubert Kario <[email protected]>Mail changed to <[email protected]> (Github version already updated.)
Updated and applied, thanks.