summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2016-08-29 16:09:02 +0800
committerDavid Sterba <dsterba@suse.com>2016-09-05 10:04:16 +0200
commit2f242115d1c3a395158d5b6d6d31ad4ae9a2c991 (patch)
tree307c9d3bd2b2d00162bde510ab34a7b1301d5f9e
parentf1934f4c7832efd362a177641c5409179555169e (diff)
btrfs-progs: Do extra chunk check before processing chunk item
Current we only do chunk validation check at mount time. It's good for most case, but for fuzzed or manually crafted images, we can insert a CHUNK_ITEM key into root tree. Since mount time check will only check chunk tree, it will not check CHUNK_ITEM in root tree. Even with previous key type check against leaf owner, it is still possible to modify the leaf owner to by-pass it. So we still need to check chunk validation before processing it. Reported-by: Lukas Lueg <lukas.lueg@gmail.com> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--cmds-check.c16
-rw-r--r--volumes.c8
-rw-r--r--volumes.h4
3 files changed, 24 insertions, 4 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 617b867f..1e1f7c9d 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -5220,8 +5220,24 @@ static int process_chunk_item(struct cache_tree *chunk_cache,
int slot)
{
struct chunk_record *rec;
+ struct btrfs_chunk *chunk;
int ret = 0;
+ chunk = btrfs_item_ptr(eb, slot, struct btrfs_chunk);
+ /*
+ * Do extra check for this chunk item,
+ *
+ * It's still possible one can craft a leaf with CHUNK_ITEM, with
+ * wrong onwer(3) out of chunk tree, to pass both chunk tree check
+ * and owner<->key_type check.
+ */
+ ret = btrfs_check_chunk_valid(global_info->tree_root, eb, chunk, slot,
+ key->offset);
+ if (ret < 0) {
+ error("chunk(%llu, %llu) is not valid, ignore it",
+ key->offset, btrfs_chunk_length(eb, chunk));
+ return 0;
+ }
rec = btrfs_new_chunk_record(eb, key, slot);
ret = insert_cache_extent(chunk_cache, &rec->cache);
if (ret) {
diff --git a/volumes.c b/volumes.c
index 9a5580ae..2d07e66a 100644
--- a/volumes.c
+++ b/volumes.c
@@ -1614,10 +1614,10 @@ static struct btrfs_device *fill_missing_device(u64 devid)
* slot == -1: SYSTEM chunk
* return -EIO on error, otherwise return 0
*/
-static int btrfs_check_chunk_valid(struct btrfs_root *root,
- struct extent_buffer *leaf,
- struct btrfs_chunk *chunk,
- int slot, u64 logical)
+int btrfs_check_chunk_valid(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_chunk *chunk,
+ int slot, u64 logical)
{
u64 length;
u64 stripe_len;
diff --git a/volumes.h b/volumes.h
index af7182b8..d7b7d3cc 100644
--- a/volumes.h
+++ b/volumes.h
@@ -226,4 +226,8 @@ int write_raid56_with_parity(struct btrfs_fs_info *info,
struct extent_buffer *eb,
struct btrfs_multi_bio *multi,
u64 stripe_len, u64 *raid_map);
+int btrfs_check_chunk_valid(struct btrfs_root *root,
+ struct extent_buffer *leaf,
+ struct btrfs_chunk *chunk,
+ int slot, u64 logical);
#endif