Skip to content

Commit 2acb5c1

Browse files
bharambetejastytso
authored andcommitted
ext4: validate p_idx bounds in ext4_ext_correct_indexes
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
1 parent 73bf12a commit 2acb5c1

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
@@ -1736,6 +1736,13 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
17361736
err = ext4_ext_get_access(handle, inode, path + k);
17371737
if (err)
17381738
return err;
1739+
if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
1740+
EXT4_ERROR_INODE(inode,
1741+
"path[%d].p_idx %p > EXT_LAST_INDEX %p",
1742+
k, path[k].p_idx,
1743+
EXT_LAST_INDEX(path[k].p_hdr));
1744+
return -EFSCORRUPTED;
1745+
}
17391746
path[k].p_idx->ei_block = border;
17401747
err = ext4_ext_dirty(handle, inode, path + k);
17411748
if (err)
@@ -1748,6 +1755,14 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
17481755
err = ext4_ext_get_access(handle, inode, path + k);
17491756
if (err)
17501757
goto clean;
1758+
if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
1759+
EXT4_ERROR_INODE(inode,
1760+
"path[%d].p_idx %p > EXT_LAST_INDEX %p",
1761+
k, path[k].p_idx,
1762+
EXT_LAST_INDEX(path[k].p_hdr));
1763+
err = -EFSCORRUPTED;
1764+
goto clean;
1765+
}
17511766
path[k].p_idx->ei_block = border;
17521767
err = ext4_ext_dirty(handle, inode, path + k);
17531768
if (err)

0 commit comments

Comments
 (0)