mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps
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. Commitf86f7a75e2("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 tof86f7a75e2. CC: Jeff Layton <jlayton@kernel.org> Link: https://lore.kernel.org/all/20260629-btrfs-skip-logging-v1-1-4e3a28c1acaf@kernel.org/ Fixes:f86f7a75e2("btrfs: use the flags of an extent map to identify the compression type") Reviewed-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Leo Martins <loemra.dev@gmail.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
committed by
David Sterba
parent
8b5a09ceb6
commit
5eff4d5b17
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user