| Message ID | 20260930134516.397754-2-Jeremy.Jean@oss.cyber.gouv.fr |
|---|---|
| State | New |
| Headers | show |
| Series | ext4: save converted extent before merging | expand |
On Wed, Sep 30, 2026 at 01:45:17PM +0000, Jérémy Jean wrote: > In ext4_split_convert_extents(), merging can release the leaf holding > the extent pointed to by ex. The later extent status cache update can > then dereference freed memory, causing a use-after-free. KASAN reports: > > BUG: KASAN: use-after-free in ext4_split_convert_extents.constprop.0+0xb98/0xc80 > Read of size 2 at addr ff11000002547034 by task fixture/65 > > Save the converted extent before merging and use the copy for the cache > update. This also avoids using the old extent slot after a merge with > the left neighbour. > > Fixes: 716b9c23b862 ("ext4: refactor split and convert extents") > Cc: stable@kernel.org > Assisted-by: LLM > Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> > --- Hey Jeremy, thanks for the fix. I'm working on a patch that has some more fixes in this area but your fix looks good standalone. Feel free to add: Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Regards, ojaswin > fs/ext4/extents.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c > index 76038b6..f5a3880 100644 > --- a/fs/ext4/extents.c > +++ b/fs/ext4/extents.c > @@ -3830,6 +3830,7 @@ static struct ext4_ext_path *ext4_split_convert_extents(handle_t *handle, > ext4_lblk_t eof_block; > ext4_lblk_t ee_block; > struct ext4_extent *ex; > + struct ext4_extent converted_ex; > unsigned int ee_len; > int split_flag = 0, depth, err = 0; > bool did_zeroout = false; > @@ -3887,6 +3888,9 @@ convert: > else if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN) > ext4_ext_mark_unwritten(ex); > > + /* Merging can move ex or release the leaf containing it. */ > + converted_ex = *ex; > + > if (!(flags & EXT4_GET_BLOCKS_SPLIT_NOMERGE)) > /* > * note: ext4_ext_correct_indexes() isn't needed here because > @@ -3897,6 +3901,7 @@ convert: > err = ext4_ext_dirty(handle, inode, path + depth); > if (err) > goto err; > + ex = &converted_ex; > } > > /* Lets update the extent status tree after conversion */ > -- > 2.47.3 >
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 76038b6..f5a3880 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3830,6 +3830,7 @@ static struct ext4_ext_path *ext4_split_convert_extents(handle_t *handle, ext4_lblk_t eof_block; ext4_lblk_t ee_block; struct ext4_extent *ex; + struct ext4_extent converted_ex; unsigned int ee_len; int split_flag = 0, depth, err = 0; bool did_zeroout = false; @@ -3887,6 +3888,9 @@ convert: else if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN) ext4_ext_mark_unwritten(ex); + /* Merging can move ex or release the leaf containing it. */ + converted_ex = *ex; + if (!(flags & EXT4_GET_BLOCKS_SPLIT_NOMERGE)) /* * note: ext4_ext_correct_indexes() isn't needed here because @@ -3897,6 +3901,7 @@ convert: err = ext4_ext_dirty(handle, inode, path + depth); if (err) goto err; + ex = &converted_ex; } /* Lets update the extent status tree after conversion */
In ext4_split_convert_extents(), merging can release the leaf holding the extent pointed to by ex. The later extent status cache update can then dereference freed memory, causing a use-after-free. KASAN reports: BUG: KASAN: use-after-free in ext4_split_convert_extents.constprop.0+0xb98/0xc80 Read of size 2 at addr ff11000002547034 by task fixture/65 Save the converted extent before merging and use the copy for the cache update. This also avoids using the old extent slot after a merge with the left neighbour. Fixes: 716b9c23b862 ("ext4: refactor split and convert extents") Cc: stable@kernel.org Assisted-by: LLM Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> --- fs/ext4/extents.c | 5 +++++ 1 file changed, 5 insertions(+)