Re: [PATCH] btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps

Jeff Layton <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <[email protected]>
On Tue, 2026-06-30 at 12:58 -0700, Leo Martins 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]>
> ---
>  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);
>  
>  		/*

Reviewed-by: Jeff Layton <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.