Commit 1373f884 authored by Jan Kara's avatar Jan Kara Committed by Greg Kroah-Hartman

ext4: don't allow overlapping system zones

[ Upstream commit bf9a379d ]

Currently, add_system_zone() just silently merges two added system zones
that overlap. However the overlap should not happen and it generally
suggests that some unrelated metadata overlap which indicates the fs is
corrupted. We should have caught such problems earlier (e.g. in
ext4_check_descriptors()) but add this check as another line of defense.
In later patch we also use this for stricter checking of journal inode
extent tree.
Reviewed-by: default avatarLukas Czerner <lczerner@redhat.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20200728130437.7804-3-jack@suse.czSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b3ddf6ba
...@@ -68,7 +68,7 @@ static int add_system_zone(struct ext4_system_blocks *system_blks, ...@@ -68,7 +68,7 @@ static int add_system_zone(struct ext4_system_blocks *system_blks,
ext4_fsblk_t start_blk, ext4_fsblk_t start_blk,
unsigned int count) unsigned int count)
{ {
struct ext4_system_zone *new_entry = NULL, *entry; struct ext4_system_zone *new_entry, *entry;
struct rb_node **n = &system_blks->root.rb_node, *node; struct rb_node **n = &system_blks->root.rb_node, *node;
struct rb_node *parent = NULL, *new_node = NULL; struct rb_node *parent = NULL, *new_node = NULL;
...@@ -79,19 +79,10 @@ static int add_system_zone(struct ext4_system_blocks *system_blks, ...@@ -79,19 +79,10 @@ static int add_system_zone(struct ext4_system_blocks *system_blks,
n = &(*n)->rb_left; n = &(*n)->rb_left;
else if (start_blk >= (entry->start_blk + entry->count)) else if (start_blk >= (entry->start_blk + entry->count))
n = &(*n)->rb_right; n = &(*n)->rb_right;
else { else /* Unexpected overlap of system zones. */
if (start_blk + count > (entry->start_blk + return -EFSCORRUPTED;
entry->count))
entry->count = (start_blk + count -
entry->start_blk);
new_node = *n;
new_entry = rb_entry(new_node, struct ext4_system_zone,
node);
break;
}
} }
if (!new_entry) {
new_entry = kmem_cache_alloc(ext4_system_zone_cachep, new_entry = kmem_cache_alloc(ext4_system_zone_cachep,
GFP_KERNEL); GFP_KERNEL);
if (!new_entry) if (!new_entry)
...@@ -102,7 +93,6 @@ static int add_system_zone(struct ext4_system_blocks *system_blks, ...@@ -102,7 +93,6 @@ static int add_system_zone(struct ext4_system_blocks *system_blks,
rb_link_node(new_node, parent, n); rb_link_node(new_node, parent, n);
rb_insert_color(new_node, &system_blks->root); rb_insert_color(new_node, &system_blks->root);
}
/* Can we merge to the left? */ /* Can we merge to the left? */
node = rb_prev(new_node); node = rb_prev(new_node);
......
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