stable inclusion from stable-v5.10.227 commit b0cb4561fc4284d04e69c8a66c8504928ab2484e category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAYR98 CVE: CVE-2024-49889
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 4e2524ba2ca5f54bdbb9e5153bea00421ef653f5 ]
In ext4_find_extent(), path may be freed by error or be reallocated, so using a previously saved *ppath may have been freed and thus may trigger use-after-free, as follows:
ext4_split_extent path = *ppath; ext4_split_extent_at(ppath) path = ext4_find_extent(ppath) ext4_split_extent_at(ppath) // ext4_find_extent fails to free path // but zeroout succeeds ext4_ext_show_leaf(inode, path) eh = path[depth].p_hdr // path use-after-free !!!
Similar to ext4_split_extent_at(), we use *ppath directly as an input to ext4_ext_show_leaf(). Fix a spelling error by the way.
Same problem in ext4_ext_handle_unwritten_extents(). Since 'path' is only used in ext4_ext_show_leaf(), remove 'path' and use *ppath directly.
This issue is triggered only when EXT_DEBUG is defined and therefore does not affect functionality.
Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Jan Kara jack@suse.cz Reviewed-by: Ojaswin Mujoo ojaswin@linux.ibm.com Tested-by: Ojaswin Mujoo ojaswin@linux.ibm.com Link: https://patch.msgid.link/20240822023545.1994557-5-libaokun@huaweicloud.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Sasha Levin sashal@kernel.org
Conflicts: fs/ext4/extents.c [Context differences because there is no commit 4337ecd1fe99 ("ext4: remove EXT4_EOFBLOCKS_FL and associated code")] Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/ext4/extents.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index e29b55991e8f..b4a0ed5dad9f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3402,7 +3402,7 @@ static int ext4_split_extent_at(handle_t *handle, }
/* - * ext4_split_extents() splits an extent and mark extent which is covered + * ext4_split_extent() splits an extent and mark extent which is covered * by @map as split_flags indicates * * It may result in splitting the extent into multiple extents (up to three) @@ -3479,7 +3479,7 @@ static int ext4_split_extent(handle_t *handle, goto out; }
- ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); out: return err ? err : allocated; } @@ -4114,7 +4114,6 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, struct ext4_ext_path **ppath, int flags, unsigned int allocated, ext4_fsblk_t newblock) { - struct ext4_ext_path *path = *ppath; int ret = 0; int err = 0;
@@ -4122,7 +4121,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, "block %llu, max_blocks %u, flags %x, allocated %u\n", inode->i_ino, (unsigned long long)map->m_lblk, map->m_len, flags, allocated); - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath);
/* * When writing into unwritten space, we should not fail to @@ -4157,7 +4156,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, if (ret >= 0) { ext4_update_inode_fsync_trans(handle, inode, 1); err = check_eofblocks_fl(handle, inode, map->m_lblk, - path, map->m_len); + *ppath, map->m_len); } else err = ret; map->m_flags |= EXT4_MAP_MAPPED; @@ -4235,7 +4234,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, map_out: map->m_flags |= EXT4_MAP_MAPPED; if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) { - err = check_eofblocks_fl(handle, inode, map->m_lblk, path, + err = check_eofblocks_fl(handle, inode, map->m_lblk, *ppath, map->m_len); if (err < 0) goto out2; @@ -4243,7 +4242,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode, out1: if (allocated > map->m_len) allocated = map->m_len; - ext4_ext_show_leaf(inode, path); + ext4_ext_show_leaf(inode, *ppath); map->m_pblk = newblock; map->m_len = allocated; out2: