* [PATCH v3] ext4: detect invalid INLINE_DATA + EXTENTS flag combination
@ 2025-09-30 10:25 Deepanshu Kartikey
2025-09-30 11:08 ` Zhang Yi
0 siblings, 1 reply; 3+ messages in thread
From: Deepanshu Kartikey @ 2025-09-30 10:25 UTC (permalink / raw)
To: tytso, adilger.kernel
Cc: yi.zhang, linux-ext4, linux-kernel, Deepanshu Kartikey,
syzbot+038b7bf43423e132b308, Zhang Yi
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.
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>
---
Changes in v3:
- Fix code alignment and use existing function/line variables per Zhang Yi
- Keep check after ret = 0 where all inode fields are initialized, as
i_inline_off gets set during inode initialization after ext4_set_inode_flags()
Changes in v2:
- Instead of adding validation in ext4_find_extent(), detect the invalid
INLINE_DATA + EXTENTS flag combination in ext4_iget() as suggested by
Zhang Yi to avoid redundant checks in the extent lookup path
---
fs/ext4/inode.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5b7a15db4953..5c97de5775c7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5445,6 +5445,15 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
}
ret = 0;
+ /* Detect invalid flag combination - can't have both inline data and extents */
+ if (ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
+ ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
+ ext4_error_inode(inode, function, line, 0,
+ "inode has both inline data and extents flags");
+ ret = -EFSCORRUPTED;
+ goto bad_inode;
+ }
+
if (ei->i_file_acl &&
!ext4_inode_block_valid(inode, ei->i_file_acl, 1)) {
ext4_error_inode(inode, function, line, 0,
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v3] ext4: detect invalid INLINE_DATA + EXTENTS flag combination
2025-09-30 10:25 [PATCH v3] ext4: detect invalid INLINE_DATA + EXTENTS flag combination Deepanshu Kartikey
@ 2025-09-30 11:08 ` Zhang Yi
0 siblings, 0 replies; 3+ messages in thread
From: Zhang Yi @ 2025-09-30 11:08 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: tytso, adilger.kernel, linux-ext4, linux-kernel,
syzbot+038b7bf43423e132b308, Zhang Yi
On 9/30/2025 6:25 PM, Deepanshu Kartikey wrote:
> 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.
>
> 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>
Thanks for the patch! It looks good to me.
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
> ---
> Changes in v3:
> - Fix code alignment and use existing function/line variables per Zhang Yi
> - Keep check after ret = 0 where all inode fields are initialized, as
> i_inline_off gets set during inode initialization after ext4_set_inode_flags()
>
> Changes in v2:
> - Instead of adding validation in ext4_find_extent(), detect the invalid
> INLINE_DATA + EXTENTS flag combination in ext4_iget() as suggested by
> Zhang Yi to avoid redundant checks in the extent lookup path
> ---
> fs/ext4/inode.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 5b7a15db4953..5c97de5775c7 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5445,6 +5445,15 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
> }
>
> ret = 0;
> + /* Detect invalid flag combination - can't have both inline data and extents */
> + if (ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
> + ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
> + ext4_error_inode(inode, function, line, 0,
> + "inode has both inline data and extents flags");
> + ret = -EFSCORRUPTED;
> + goto bad_inode;
> + }
> +
> if (ei->i_file_acl &&
> !ext4_inode_block_valid(inode, ei->i_file_acl, 1)) {
> ext4_error_inode(inode, function, line, 0,
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3] ext4: detect invalid INLINE_DATA + EXTENTS flag combination
@ 2025-09-30 11:26 Deepanshu Kartikey
0 siblings, 0 replies; 3+ messages in thread
From: Deepanshu Kartikey @ 2025-09-30 11:26 UTC (permalink / raw)
To: tytso, adilger.kernel, yi.zhang; +Cc: linux-ext4, linux-kernel
Zhang Yi,
Thank you for the clarification about checking flags directly versus
ext4_has_inline_data() return value. You're absolutely right - since
I'm checking the flags themselves which don't change after being set
from disk, the check can and should be placed right after
ext4_set_inode_flags().
I've sent v4 with the check moved to the earlier location as you
suggested. This placement is indeed more logical - detecting invalid
flag combinations immediately after reading them from disk.
The patch has been tested by syzbot and confirms it fixes the issue.
Thank you for your patience and thorough review that helped identify
the proper fix for this issue.
Best regards,
Deepanshu
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-09-30 11:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-30 10:25 [PATCH v3] ext4: detect invalid INLINE_DATA + EXTENTS flag combination Deepanshu Kartikey
2025-09-30 11:08 ` Zhang Yi
-- strict thread matches above, loose matches on Subject: below --
2025-09-30 11:26 Deepanshu Kartikey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).