Skip to content

Commit de98526

Browse files
deepanshu406gregkh
authored andcommitted
ext4: detect invalid INLINE_DATA + EXTENTS flag combination
commit 1d3ad18 upstream. syzbot reported a BUG_ON in ext4_es_cache_extent() when opening a verity file on a corrupted ext4 filesystem mounted without a journal. The issue is that the filesystem has an inode with both the INLINE_DATA and EXTENTS flags set: EXT4-fs error (device loop0): ext4_cache_extents:545: inode #15: comm syz.0.17: corrupted extent tree: lblk 0 < prev 66 Investigation revealed that the inode has both flags set: DEBUG: inode 15 - flag=1, i_inline_off=164, has_inline=1, extents_flag=1 This is an invalid combination since an inode should have either: - INLINE_DATA: data stored directly in the inode - EXTENTS: data stored in extent-mapped blocks Having both flags causes ext4_has_inline_data() to return true, skipping extent tree validation in __ext4_iget(). The unvalidated out-of-order extents then trigger a BUG_ON in ext4_es_cache_extent() due to integer underflow when calculating hole sizes. Fix this by detecting this invalid flag combination early in ext4_iget() and rejecting the corrupted inode. Cc: [email protected] Reported-and-tested-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=038b7bf43423e132b308 Suggested-by: Zhang Yi <[email protected]> Signed-off-by: Deepanshu Kartikey <[email protected]> Reviewed-by: Zhang Yi <[email protected]> Message-ID: <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5b7b9a1 commit de98526

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

fs/ext4/inode.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4904,6 +4904,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
49044904
}
49054905
ei->i_flags = le32_to_cpu(raw_inode->i_flags);
49064906
ext4_set_inode_flags(inode, true);
4907+
/* Detect invalid flag combination - can't have both inline data and extents */
4908+
if (ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
4909+
ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
4910+
ext4_error_inode(inode, function, line, 0,
4911+
"inode has both inline data and extents flags");
4912+
ret = -EFSCORRUPTED;
4913+
goto bad_inode;
4914+
}
49074915
inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
49084916
ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
49094917
if (ext4_has_feature_64bit(sb))

0 commit comments

Comments
 (0)