Commit f556faa4 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: tree-checker: Check level for leaves and nodes

Although we have tree level check at tree read runtime, it's completely
based on its parent level.
We still need to do accurate level check to avoid invalid tree blocks
sneak into kernel space.

The check itself is simple, for leaf its level should always be 0.
For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarSu Yue <suy.fnst@cn.fujitsu.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 3d0174f7
...@@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, ...@@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf,
u32 nritems = btrfs_header_nritems(leaf); u32 nritems = btrfs_header_nritems(leaf);
int slot; int slot;
if (btrfs_header_level(leaf) != 0) {
generic_err(fs_info, leaf, 0,
"invalid level for leaf, have %d expect 0",
btrfs_header_level(leaf));
return -EUCLEAN;
}
/* /*
* Extent buffers from a relocation tree have a owner field that * Extent buffers from a relocation tree have a owner field that
* corresponds to the subvolume tree they are based on. So just from an * corresponds to the subvolume tree they are based on. So just from an
...@@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info *fs_info, struct extent_buffer *node) ...@@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info *fs_info, struct extent_buffer *node)
unsigned long nr = btrfs_header_nritems(node); unsigned long nr = btrfs_header_nritems(node);
struct btrfs_key key, next_key; struct btrfs_key key, next_key;
int slot; int slot;
int level = btrfs_header_level(node);
u64 bytenr; u64 bytenr;
int ret = 0; int ret = 0;
if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
generic_err(fs_info, node, 0,
"invalid level for node, have %d expect [1, %d]",
level, BTRFS_MAX_LEVEL - 1);
return -EUCLEAN;
}
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
btrfs_crit(fs_info, btrfs_crit(fs_info,
"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment