Btrfs tree implies a lot of restriction on which key types are allowed in specific roots.
Like CHUNK_ITEM keys are only valid in chunk root. This patch will add such check at run_next_block() for original mode. Reported-by: Lukas Lueg <lukas.l...@gmail.com> Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com> --- cmds-check.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/cmds-check.c b/cmds-check.c index 0ddfd24..617b867 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -6122,6 +6122,58 @@ full_backref: return 0; } +static void report_mismatch_key_root(u8 key_type, u64 rootid) +{ + fprintf(stderr, "Invalid key type("); + print_key_type(stderr, 0, key_type); + fprintf(stderr, ") found in root("); + print_objectid(stderr, rootid, 0); + fprintf(stderr, ")\n"); +} + +/* + * Check if the key is valid with its extent buffer. + * + * This is a early check in case invalid key exists in a extent buffer + * This is not comprehensive yet, but should prevent wrong key/item passed + * further + */ +static int check_type_with_root(u64 rootid, u8 key_type) +{ + switch (key_type) { + /* Only valid in chunk tree */ + case BTRFS_DEV_ITEM_KEY: + case BTRFS_CHUNK_ITEM_KEY: + if (rootid != BTRFS_CHUNK_TREE_OBJECTID) + goto err; + break; + /* valid in csum and log tree */ + case BTRFS_CSUM_TREE_OBJECTID: + if (!(rootid == BTRFS_TREE_LOG_OBJECTID || + is_fstree(rootid))) + goto err; + break; + case BTRFS_EXTENT_ITEM_KEY: + case BTRFS_METADATA_ITEM_KEY: + case BTRFS_BLOCK_GROUP_ITEM_KEY: + if (rootid != BTRFS_EXTENT_TREE_OBJECTID) + goto err; + break; + case BTRFS_ROOT_ITEM_KEY: + if (rootid != BTRFS_ROOT_TREE_OBJECTID) + goto err; + break; + case BTRFS_DEV_EXTENT_KEY: + if (rootid != BTRFS_DEV_TREE_OBJECTID) + goto err; + break; + } + return 0; +err: + report_mismatch_key_root(key_type, rootid); + return -EINVAL; +} + static int run_next_block(struct btrfs_root *root, struct block_info *bits, int bits_nr, @@ -6271,6 +6323,16 @@ static int run_next_block(struct btrfs_root *root, for (i = 0; i < nritems; i++) { struct btrfs_file_extent_item *fi; btrfs_item_key_to_cpu(buf, &key, i); + /* + * Check key type against the leaf owner. + * Could filter quite a lot of early error if + * owner is correct + */ + if (check_type_with_root(btrfs_header_owner(buf), + key.type)) { + fprintf(stderr, "ignoring invalid key\n"); + continue; + } if (key.type == BTRFS_EXTENT_ITEM_KEY) { process_extent_item(root, extent_cache, buf, i); -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html