ext4: fix infinite loop when replaying fast_commit
PATCH v2 1/1 ext4: fix infinite loop when replaying fast_commit
When doing fast_commit replay an infinite loop may occur due to an uninitialized extent_status struct. ext4_ext_determine_insert_hole() does not detect the replay and calls ext4_es_find_extent_range(), which will return immediately without initializing the 'es' variable.
Because 'es' contains garbage, an integer overflow may happen causing an infinite loop in this function, easily reproducible using fstest generic/039.
This commit fixes this issue by unconditionally initializing the structure in function ext4_es_find_extent_range().
Thanks to Zhang Yi, for figuring out the real problem!
--- fs/ext4/extents_status.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ext4/extents_status.c +2 -0
@@ -310,6 +310,8 @@ void ext4_es_find_extent_range(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t end, struct extent_status *es) { + es->es_lblk = es->es_len = es->es_pblk = 0; +if (EXT4_SB (inode->i_sb)->s_mount_state &EXT4_FC_REPLAY )return ;
Quoted 8 lines · Luis Henriques (SUSE)
When doing
fast_commitreplay an infinite loop may occur due to an uninitializedextent_statusstruct.ext4_ext_determine_insert_hole()does not detect the replay and callsext4_es_find_extent_range(), which will return immediately without initializing the 'es' variable.Because 'es' contains garbage, an integer overflow may happen causing an infinite loop in this function, easily reproducible using fstest generic/039.
Quoted 7 lines
This commit fixes this issue by unconditionally initializing the structure in function
ext4_es_find_extent_range().Thanks to Zhang Yi, for figuring out the real problem!
Fixes 8016e29f4362 ("ext4: fast commit recovery path")Signed-off-by Luis Henriques (SUSE) <[email protected]>
Thanks for fixing this issue,looks good to me.
Quoted 18 lines
--- fs/ext4/extents_status.c | 2 ++ 1 file changed, 2 insertions(+)fs/ext4/extents_status.c +2
-0@@ -310,6 +310,8 @@ void ext4_es_find_extent_range(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t end, struct extent_status *es) { + es->es_lblk = es->es_len = es->es_pblk = 0; +if (EXT4_SB (inode->i_sb)->s_mount_state &EXT4_FC_REPLAY )return ;
Quoted 8 lines · Luis Henriques (SUSE)
When doing
fast_commitreplay an infinite loop may occur due to an uninitializedextent_statusstruct.ext4_ext_determine_insert_hole()does not detect the replay and callsext4_es_find_extent_range(), which will return immediately without initializing the 'es' variable.Because 'es' contains garbage, an integer overflow may happen causing an infinite loop in this function, easily reproducible using fstest generic/039.
Quoted 7 lines
This commit fixes this issue by unconditionally initializing the structure in function
ext4_es_find_extent_range().Thanks to Zhang Yi, for figuring out the real problem!
Fixes 8016e29f4362 ("ext4: fast commit recovery path")Signed-off-by Luis Henriques (SUSE) <[email protected]>
Gentle ping... Has this fell through the cracks?
Cheers,
Signature · 1 line
Luis
Quoted 17 lines
--- fs/ext4/extents_status.c | 2 ++ 1 file changed, 2 insertions(+)fs/ext4/extents_status.c +2
-0@@ -310,6 +310,8 @@ void ext4_es_find_extent_range(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t end, struct extent_status *es) { + es->es_lblk = es->es_len = es->es_pblk = 0; +if (EXT4_SB (inode->i_sb)->s_mount_state &EXT4_FC_REPLAY )return ;
Quoted 9 lines · Luis Henriques (SUSE)
When doing
fast_commitreplay an infinite loop may occur due to an uninitializedextent_statusstruct.ext4_ext_determine_insert_hole()does not detect the replay and callsext4_es_find_extent_range(), which will return immediately without initializing the 'es' variable.Because 'es' contains garbage, an integer overflow may happen causing an infinite loop in this function, easily reproducible using fstest generic/039.
[...]
Applied, thanks!
[1/1] ext4: fix infinite loop when replaying fast_commit
commit: 907c3fe532253a6ef4eb9c4d67efb71fab58c706
Best regards,
Signature · 1 line
Theodore Ts'o <[email protected]>