syzbot reported a BUG_ON in ext4_es_cache_extent() triggered when opening a verity file on a corrupted ext4 filesystem mounted without a journal. The issue occurs when the extent tree contains out-of-order extents, which can happen in a corrupted filesystem. ext4_find_extent() calls ext4_cache_extents() without validating the extent entries when the tree depth is 0 (leaf level). This allows corrupted extent trees with out-of-order extents to be cached, triggering a BUG_ON in ext4_es_cache_extent() due to integer underflow when calculating hole sizes: If prev = 4352 and lblk = 1280: lblk - prev = 1280 - 4352 = -3072 (as signed) = 4294964224 (as unsigned) end = lblk + len - 1 = 4352 + 4294964224 - 1 = 1279 (after overflow) BUG_ON(end < lblk) triggers because 1279 < 4352 Fix this by adding extent entry validation using the existing ext4_valid_extent_entries() function before caching. This ensures corrupted extent trees are detected and handled properly through the error path, preventing both the BUG_ON and potential use-after-free issues. Reported-and-tested-by: syzbot+038b7bf43423e132b308@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=038b7bf43423e132b308 Signed-off-by: Deepanshu Kartikey --- fs/ext4/extents.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ca5499e9412b..f8e45623f7ea 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -924,8 +924,18 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, path[0].p_bh = NULL; i = depth; - if (!(flags & EXT4_EX_NOCACHE) && depth == 0) + if (!(flags & EXT4_EX_NOCACHE) && depth == 0) { + ext4_fsblk_t pblk = 0; + + if (!ext4_valid_extent_entries(inode, eh, 0, &pblk, 0)) { + EXT4_ERROR_INODE(inode, + "invalid extent entries, pblk %llu", + pblk); + ret = -EFSCORRUPTED; + goto err; + } ext4_cache_extents(inode, eh); + } /* walk through the tree */ while (i) { ext_debug(inode, "depth %d: num %d, max %d\n", -- 2.43.0