Re: [PATCH] btrfs: fix transaction use-after-free in raid stripe insertion
Qu Wenruo <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
在 2026/8/17 11:39, Shuangpeng 写道: > > >> On Aug 16, 2026, at 21:58, Qu Wenruo <[email protected]> wrote: >> >> >> >> 在 2026/8/17 10:57, Shuangpeng Bai 写道: >>> If allocation of a RAID stripe extent fails, >>> btrfs_insert_one_raid_extent() aborts and ends the transaction before >>> returning -ENOMEM. >>> btrfs_finish_one_ordered(), the production caller through >>> btrfs_insert_raid_extent(), still owns the transaction handle. It handles >>> the error by aborting the transaction and then reaches the common exit >>> path, which ends the transaction again. >>> The premature end can free the handle and drop its transaction reference. >>> Transaction cleanup can then free the transaction before the caller's >>> second abort accesses the handle and transaction, resulting in >>> use-after-free. >>> Keep the abort at the failure site, but let the caller's common exit path >>> end the transaction once, after it has finished using both objects. >>> Fixes: 02c372e1f016 ("btrfs: add support for inserting raid stripe extents") >>> Cc: [email protected] >> >> Please disclose LLM usage. >> > > Hi Qu, > > Thanks for pointing this out. > > I used Codex to help generate the patch. I had confirmed the bug with KASAN, > and I also verified the proposed fix with my reproducer. With the patch applied, > the reproducer no longer triggers the KASAN report. And a full fstests run to prevent regression. > > I will send a v2 with the appropriate LLM disclosure tag. > > Thanks, > Shuangpeng > >>> Signed-off-by: Shuangpeng Bai <[email protected]> >>> --- >>> fs/btrfs/raid-stripe-tree.c | 1 - >>> 1 file changed, 1 deletion(-) >>> diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c >>> index b210371ce91e..89e259a47d8d 100644 >>> --- a/fs/btrfs/raid-stripe-tree.c >>> +++ b/fs/btrfs/raid-stripe-tree.c >>> @@ -337,7 +337,6 @@ int btrfs_insert_one_raid_extent(struct btrfs_trans_handle *trans, >>> stripe_extent = kzalloc(item_size, GFP_NOFS); >>> if (unlikely(!stripe_extent)) { >>> btrfs_abort_transaction(trans, -ENOMEM); >>> - btrfs_end_transaction(trans); >>> return -ENOMEM; >>> } >>> >> >