Skip to content

Commit 1f5ccd2

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 torvalds#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: stable@kernel.org Reported-and-tested-by: syzbot+038b7bf43423e132b308@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=038b7bf43423e132b308 Suggested-by: Zhang Yi <yi.zhang@huawei.com> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com> Reviewed-by: Zhang Yi <yi.zhang@huawei.com> Message-ID: <20250930112810.315095-1-kartikey406@gmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 77e5cbd commit 1f5ccd2

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
@@ -5319,6 +5319,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
53195319
}
53205320
ei->i_flags = le32_to_cpu(raw_inode->i_flags);
53215321
ext4_set_inode_flags(inode, true);
5322+
/* Detect invalid flag combination - can't have both inline data and extents */
5323+
if (ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
5324+
ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
5325+
ext4_error_inode(inode, function, line, 0,
5326+
"inode has both inline data and extents flags");
5327+
ret = -EFSCORRUPTED;
5328+
goto bad_inode;
5329+
}
53225330
inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
53235331
ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
53245332
if (ext4_has_feature_64bit(sb))

0 commit comments

Comments
 (0)