[PATCH 6.6.y] ext4: validate p_idx bounds in ext4_ext_correct_indexes

Jianqiang kang posted 1 patch 3 weeks, 1 day ago
fs/ext4/extents.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
[PATCH 6.6.y] ext4: validate p_idx bounds in ext4_ext_correct_indexes
Posted by Jianqiang kang 3 weeks, 1 day ago
From: Tejas Bharambe <tejas.bharambe@outlook.com>

[ Upstream commit 2acb5c12ebd860f30e4faf67e6cc8c44ddfe5fe8 ]

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>
---
 fs/ext4/extents.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 7626cf2b07f1..a94798e23c1a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1743,6 +1743,13 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
 	err = ext4_ext_get_access(handle, inode, path + k);
 	if (err)
 		return err;
+	if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
+		EXT4_ERROR_INODE(inode,
+				 "path[%d].p_idx %p > EXT_LAST_INDEX %p",
+				 k, path[k].p_idx,
+				 EXT_LAST_INDEX(path[k].p_hdr));
+		return -EFSCORRUPTED;
+	}
 	path[k].p_idx->ei_block = border;
 	err = ext4_ext_dirty(handle, inode, path + k);
 	if (err)
@@ -1755,6 +1762,14 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
 		err = ext4_ext_get_access(handle, inode, path + k);
 		if (err)
 			break;
+		if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
+			EXT4_ERROR_INODE(inode,
+					 "path[%d].p_idx %p > EXT_LAST_INDEX %p",
+					 k, path[k].p_idx,
+					 EXT_LAST_INDEX(path[k].p_hdr));
+			err = -EFSCORRUPTED;
+			break;
+		}
 		path[k].p_idx->ei_block = border;
 		err = ext4_ext_dirty(handle, inode, path + k);
 		if (err)
-- 
2.34.1
Re: [PATCH 6.6.y] ext4: validate p_idx bounds in ext4_ext_correct_indexes
Posted by Sasha Levin 3 weeks ago
> Subject: [PATCH 6.6.y] ext4: validate p_idx bounds in ext4_ext_correct_indexes
>
> commit 2acb5c12ebd860f30e4faf67e6cc8c44ddfe5fe8 upstream.

Now queued for 6.6 and 6.1, thanks.

--
Thanks,
Sasha
Re: [PATCH 6.6.y] ext4: validate p_idx bounds in ext4_ext_correct_indexes
Posted by Andreas Dilger 3 weeks, 1 day ago
On May 8, 2026, at 00:58, Jianqiang kang <jianqkang@sina.cn> wrote:
> 
> From: Tejas Bharambe <tejas.bharambe@outlook.com>
> 
> [ Upstream commit 2acb5c12ebd860f30e4faf67e6cc8c44ddfe5fe8 ]
> 
> 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.

Thank you for your patch.

Do you have an image with this corruption in place?  Does e2fsck fix
the issue? If not, then ext4 will abort the filesystem when this issue
is hit, and if e2fsck can't fix it then it will just be hit again.

Cheers, Andreas

> 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>
> ---
> fs/ext4/extents.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
> 
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 7626cf2b07f1..a94798e23c1a 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -1743,6 +1743,13 @@ static int ext4_ext_correct_indexes(handle_t *handle,
>  	err = ext4_ext_get_access(handle, inode, path + k);
>  	if (err)
>  	return err;
> +	if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
> +		EXT4_ERROR_INODE(inode,
> +				 "path[%d].p_idx %p > EXT_LAST_INDEX %p",
> +				 k, path[k].p_idx,
> +				 EXT_LAST_INDEX(path[k].p_hdr));
> +		return -EFSCORRUPTED;
> +	}
>  	path[k].p_idx->ei_block = border;
>  	err = ext4_ext_dirty(handle, inode, path + k);
>  	if (err)
> @@ -1755,6 +1762,14 @@ static int ext4_ext_correct_indexes(handle_t *handle,
>  		err = ext4_ext_get_access(handle, inode, path + k);
>  		if (err)
>  			break;
> +		if (unlikely(path[k].p_idx > EXT_LAST_INDEX(path[k].p_hdr))) {
> +			EXT4_ERROR_INODE(inode,
> +					 "path[%d].p_idx %p > EXT_LAST_INDEX %p",
> +					 k, path[k].p_idx,
> +					 EXT_LAST_INDEX(path[k].p_hdr));
> +			err = -EFSCORRUPTED;
> +			break;
> +		}
>  		path[k].p_idx->ei_block = border;
>  		err = ext4_ext_dirty(handle, inode, path + k);
>  		if (err)
> -- 
> 2.34.1
> 


Cheers, Andreas