Skip to content

Commit 4d08401

Browse files
bharambetejasgregkh
authored andcommitted
ext4: validate p_idx bounds in ext4_ext_correct_indexes
[ Upstream commit 2acb5c1 ] ext4_ext_correct_indexes() walks up the extent tree correcting index entries when the first extent in a leaf is modified. Before accessing path[k].p_idx->ei_block, there is no validation that p_idx falls within the valid range of index entries for that level. If the on-disk extent header contains a corrupted or crafted eh_entries value, p_idx can point past the end of the allocated buffer, causing a slab-out-of-bounds read. Fix this by validating path[k].p_idx against EXT_LAST_INDEX() at both access sites: before the while loop and inside it. Return -EFSCORRUPTED if the index pointer is out of range, consistent with how other bounds violations are handled in the ext4 extent tree code. Reported-by: syzbot+04c4e65cab786a2e5b7e@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=04c4e65cab786a2e5b7e Signed-off-by: Tejas Bharambe <tejas.bharambe@outlook.com> Link: https://patch.msgid.link/JH0PR06MB66326016F9B6AD24097D232B897CA@JH0PR06MB6632.apcprd06.prod.outlook.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@kernel.org [ Minor conflict resolved. ] Signed-off-by: Jianqiang kang <jianqkang@sina.cn> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent e3bf143 commit 4d08401

1 file changed

Lines changed: 15 additions & 0 deletions

File tree

fs/ext4/extents.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,13 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
17431743
err = ext4_ext_get_access(handle, inode, path + k);
17441744
if (err)
17451745
return err;
1746+
if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
1747+
EXT4_ERROR_INODE(inode,
1748+
"path[%d].p_idx %p > EXT_LAST_INDEX %p",
1749+
k, path[k].p_idx,
1750+
EXT_LAST_INDEX(path[k].p_hdr));
1751+
return -EFSCORRUPTED;
1752+
}
17461753
path[k].p_idx->ei_block = border;
17471754
err = ext4_ext_dirty(handle, inode, path + k);
17481755
if (err)
@@ -1755,6 +1762,14 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
17551762
err = ext4_ext_get_access(handle, inode, path + k);
17561763
if (err)
17571764
break;
1765+
if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
1766+
EXT4_ERROR_INODE(inode,
1767+
"path[%d].p_idx %p > EXT_LAST_INDEX %p",
1768+
k, path[k].p_idx,
1769+
EXT_LAST_INDEX(path[k].p_hdr));
1770+
err = -EFSCORRUPTED;
1771+
break;
1772+
}
17581773
path[k].p_idx->ei_block = border;
17591774
err = ext4_ext_dirty(handle, inode, path + k);
17601775
if (err)

0 commit comments

Comments
 (0)