Re: [PATCH] btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps
Filipe Manana <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <CAL3q7H7TpSKG+YRG5eq-iZuuy_kz6L=_PQ1d0VZFrmUreN_9zQ@mail.gmail.com> |
On Tue, Jun 30, 2026 at 8:58 PM Leo Martins <[email protected]> wrote: > > When btrfs_drop_extent_map_range() splits an extent map, the new split > maps inherit the original map's flags through a local 'flags' variable. > Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify > the compression type") changed the EXTENT_FLAG_LOGGING clearing to > operate on em->flags instead of that local 'flags' copy, so a split of > an extent map that is currently being logged wrongly inherits > EXTENT_FLAG_LOGGING. > > The flag is then never cleared on the split, and when it is freed while > still on the inode's modified_extents list (for example by the extent > map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in > btrfs_free_extent_map() and leads to a use-after-free. > > Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the > splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the > behaviour prior to f86f7a75e2fb. > > Fixes: f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type") > Cc: Jeff Layton <[email protected]> > Cc: Boris Burkov <[email protected]> > Signed-off-by: Leo Martins <[email protected]> Reviewed-by: Filipe Manana <[email protected]> Adding it to for-next, thanks. > --- > fs/btrfs/extent_map.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c > index fce9c5cc0122..6ad7b39ae358 100644 > --- a/fs/btrfs/extent_map.c > +++ b/fs/btrfs/extent_map.c > @@ -866,13 +866,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, > goto next; > } > > - flags = em->flags; > /* > * In case we split the extent map, we want to preserve the > * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want > * it on the new extent maps. > */ > - em->flags &= ~(EXTENT_FLAG_PINNED | EXTENT_FLAG_LOGGING); > + flags = em->flags & ~EXTENT_FLAG_LOGGING; > + em->flags &= ~EXTENT_FLAG_PINNED; > modified = !list_empty(&em->list); > > /* > -- > 2.53.0-Meta > >