summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2026-02-19 17:03:53 +0000
committerDavid Sterba <dsterba@suse.com>2026-03-17 11:43:08 +0100
commit057495ccc0ad381015b45d3edf995c2b6b982474 (patch)
treeaf9348355aa9bc944b2ccd82ee1b379d92275f39
parent5118130e722b1261a2e92b2fb0b067463c39ecc7 (diff)
btrfs: hold block group reference during entire move_existing_remap()
There is a potential use-after-free in move_existing_remap(): we're calling btrfs_put_block_group() on dest_bg, then passing it to btrfs_add_block_group_free_space() a few lines later. Fix this by getting the BG at the start of the function and putting it near the end. This also means we're not doing a lookup twice for the same thing. Reported-by: Chris Mason <clm@fb.com> Link: https://lore.kernel.org/linux-btrfs/20260125123908.2096548-1-clm@meta.com/ Fixes: bbea42dfb91f ("btrfs: move existing remaps before relocating block group") Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Mark Harmstone <mark@harmstone.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/relocation.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 2625a66054d0..0f61bdf7f5d1 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4185,6 +4185,8 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
dest_addr = ins.objectid;
dest_length = ins.offset;
+ dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
+
if (!is_data && !IS_ALIGNED(dest_length, fs_info->nodesize)) {
u64 new_length = ALIGN_DOWN(dest_length, fs_info->nodesize);
@@ -4295,15 +4297,12 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
if (unlikely(ret))
goto end;
- dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
-
adjust_block_group_remap_bytes(trans, dest_bg, dest_length);
mutex_lock(&dest_bg->free_space_lock);
bg_needs_free_space = test_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE,
&dest_bg->runtime_flags);
mutex_unlock(&dest_bg->free_space_lock);
- btrfs_put_block_group(dest_bg);
if (bg_needs_free_space) {
ret = btrfs_add_block_group_free_space(trans, dest_bg);
@@ -4333,13 +4332,13 @@ end:
btrfs_end_transaction(trans);
}
} else {
- dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
btrfs_free_reserved_bytes(dest_bg, dest_length, 0);
- btrfs_put_block_group(dest_bg);
ret = btrfs_commit_transaction(trans);
}
+ btrfs_put_block_group(dest_bg);
+
return ret;
}