diff options
Diffstat (limited to 'queue-6.12/btrfs-fix-use-after-free-on-inode-when-scanning-root.patch')
-rw-r--r-- | queue-6.12/btrfs-fix-use-after-free-on-inode-when-scanning-root.patch | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/queue-6.12/btrfs-fix-use-after-free-on-inode-when-scanning-root.patch b/queue-6.12/btrfs-fix-use-after-free-on-inode-when-scanning-root.patch new file mode 100644 index 0000000000..a27a16bcdf --- /dev/null +++ b/queue-6.12/btrfs-fix-use-after-free-on-inode-when-scanning-root.patch @@ -0,0 +1,54 @@ +From 5d075b4c9c1810fc58c42a4fa5292e74ba3f5c64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 2 Jul 2025 19:02:58 -0400 +Subject: btrfs: fix use-after-free on inode when scanning root during em + shrinking + +[ Upstream commit 59f37036bb7ab3d554c24abc856aabca01126414 ] + +At btrfs_scan_root() we are accessing the inode's root (and fs_info) in a +call to btrfs_fs_closing() after we have scheduled the inode for a delayed +iput, and that can result in a use-after-free on the inode in case the +cleaner kthread does the iput before we dereference the inode in the call +to btrfs_fs_closing(). + +Fix this by using the fs_info stored already in a local variable instead +of doing inode->root->fs_info. + +Fixes: 102044384056 ("btrfs: make the extent map shrinker run asynchronously as a work queue job") +CC: stable@vger.kernel.org # 6.13+ +Tested-by: Ivan Shapovalov <intelfx@intelfx.name> +Link: https://lore.kernel.org/linux-btrfs/0414d690ac5680d0d77dfc930606cdc36e42e12f.camel@intelfx.name/ +Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> +Reviewed-by: Qu Wenruo <wqu@suse.com> +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/btrfs/extent_map.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 93043edc8ff93..36af9aa9aab13 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -1250,6 +1250,7 @@ static struct btrfs_inode *find_first_inode_to_shrink(struct btrfs_root *root, + + static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx *ctx) + { ++ struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_inode *inode; + long nr_dropped = 0; + u64 min_ino = ctx->last_ino + 1; +@@ -1264,7 +1265,7 @@ static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx + iput(&inode->vfs_inode); + + if (ctx->scanned >= ctx->nr_to_scan || +- btrfs_fs_closing(inode->root->fs_info)) ++ btrfs_fs_closing(fs_info)) + break; + + cond_resched(); +-- +2.39.5 + |