summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2019-03-20 13:42:33 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-11-10 12:35:56 +0100
commit3c06c86cd08fdabe2ed20cbc3ea5010dcd7d4b29 (patch)
tree913160d2e7a57af74720ce723b8b47e995ed4fbe
parent782aa87c8f1d4472fc45697fdddbe8d47b56ebff (diff)
downloadlinux-stable-3c06c86cd08fdabe2ed20cbc3ea5010dcd7d4b29.tar.gz
linux-stable-3c06c86cd08fdabe2ed20cbc3ea5010dcd7d4b29.tar.bz2
linux-stable-3c06c86cd08fdabe2ed20cbc3ea5010dcd7d4b29.zip
btrfs: tree-checker: Check chunk item at tree block read time
commit 075cb3c78fe7976c9f29ca1fa23f9728634ecefc upstream. Since we have btrfs_check_chunk_valid() in tree-checker, let's do chunk item verification in tree-checker too. Since the tree-checker is run at endio time, if one chunk leaf fails chunk verification, we can still retry the other copy, making btrfs more robust to fuzzed image as we may still get a good chunk item. Also since we have done chunk verification in tree block read time, skip the btrfs_check_chunk_valid() call in read_one_chunk() if we're reading chunk items from leaf. Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/tree-checker.c6
-rw-r--r--fs/btrfs/volumes.c12
2 files changed, 15 insertions, 3 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 7b59a3dfb5a8..e7099300d3e0 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -608,6 +608,7 @@ static int check_leaf_item(struct btrfs_fs_info *fs_info,
struct btrfs_key *key, int slot)
{
int ret = 0;
+ struct btrfs_chunk *chunk;
switch (key->type) {
case BTRFS_EXTENT_DATA_KEY:
@@ -624,6 +625,11 @@ static int check_leaf_item(struct btrfs_fs_info *fs_info,
case BTRFS_BLOCK_GROUP_ITEM_KEY:
ret = check_block_group_item(fs_info, leaf, key, slot);
break;
+ case BTRFS_CHUNK_ITEM_KEY:
+ chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
+ ret = btrfs_check_chunk_valid(fs_info, leaf, chunk,
+ key->offset);
+ break;
}
return ret;
}
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3050a93ae6f5..8e9d855dceba 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6401,9 +6401,15 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key,
length = btrfs_chunk_length(leaf, chunk);
num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
- ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical);
- if (ret)
- return ret;
+ /*
+ * Only need to verify chunk item if we're reading from sys chunk array,
+ * as chunk item in tree block is already verified by tree-checker.
+ */
+ if (leaf->start == BTRFS_SUPER_INFO_OFFSET) {
+ ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, logical);
+ if (ret)
+ return ret;
+ }
read_lock(&map_tree->map_tree.lock);
em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);