* [PATCH] btrfs: fix use-after-free on quota enable allocation failure
@ 2026-10-07 9:06 pavankumaryalagada
2026-10-07 9:17 ` Qu Wenruo
0 siblings, 1 reply; 6+ messages in thread
From: pavankumaryalagada @ 2026-10-07 9:06 UTC (permalink / raw)
To: dsterba
Cc: mason, wqu, fdmanana, shuah, linux-btrfs, linux-kernel,
Yalagada Pavan Kumar, syzbot+947286c775f432b073a8
From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com>
The quota root remains on the transaction's dirty root list when
kzalloc_obj() fails and btrfs_quota_enable() releases it without
aborting the transaction. Later add_root_to_dirty_list() then accesses
the freed dirty_list, causing a slab-use-after-free.
Abort the transaction on allocation failure to clean up the dirty
root before releasing the quota root.
Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8
Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to reduce GFP_ATOMIC usage")
Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com>
---
fs/btrfs/qgroup.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index f68b696b4bf7..42be06675c90 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info,
prealloc = kzalloc_obj(*prealloc, GFP_NOFS);
if (!prealloc) {
ret = -ENOMEM;
+ btrfs_abort_transaction(trans, ret);
goto out_free_path;
}
qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] btrfs: fix use-after-free on quota enable allocation failure 2026-10-07 9:06 [PATCH] btrfs: fix use-after-free on quota enable allocation failure pavankumaryalagada @ 2026-10-07 9:17 ` Qu Wenruo 2026-10-07 9:22 ` Qu Wenruo 2026-10-07 9:59 ` Qu Wenruo 0 siblings, 2 replies; 6+ messages in thread From: Qu Wenruo @ 2026-10-07 9:17 UTC (permalink / raw) To: pavankumaryalagada, dsterba Cc: mason, fdmanana, shuah, linux-btrfs, linux-kernel, syzbot+947286c775f432b073a8 在 2026/10/7 19:36, pavankumaryalagada@gmail.com 写道: > From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> > > The quota root remains on the transaction's dirty root list when > kzalloc_obj() fails and btrfs_quota_enable() releases it without > aborting the transaction. Later add_root_to_dirty_list() then accesses > the freed dirty_list, causing a slab-use-after-free. > > Abort the transaction on allocation failure to clean up the dirty > root before releasing the quota root. > > Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8 > Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to reduce GFP_ATOMIC usage") > Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> Reviewed-by: Qu Wenruo <wqu@suse.com> > --- > fs/btrfs/qgroup.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index f68b696b4bf7..42be06675c90 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info, > prealloc = kzalloc_obj(*prealloc, GFP_NOFS); > if (!prealloc) { > ret = -ENOMEM; > + btrfs_abort_transaction(trans, ret); > goto out_free_path; > } > qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID); ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] btrfs: fix use-after-free on quota enable allocation failure 2026-10-07 9:17 ` Qu Wenruo @ 2026-10-07 9:22 ` Qu Wenruo 2026-10-07 9:59 ` Qu Wenruo 1 sibling, 0 replies; 6+ messages in thread From: Qu Wenruo @ 2026-10-07 9:22 UTC (permalink / raw) To: pavankumaryalagada, dsterba Cc: mason, fdmanana, shuah, linux-btrfs, linux-kernel, syzbot+947286c775f432b073a8 在 2026/10/7 19:47, Qu Wenruo 写道: > > > 在 2026/10/7 19:36, pavankumaryalagada@gmail.com 写道: >> From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> >> >> The quota root remains on the transaction's dirty root list when >> kzalloc_obj() fails and btrfs_quota_enable() releases it without >> aborting the transaction. Later add_root_to_dirty_list() then accesses >> the freed dirty_list, causing a slab-use-after-free. >> >> Abort the transaction on allocation failure to clean up the dirty >> root before releasing the quota root. >> >> Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com >> Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8 >> Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to >> reduce GFP_ATOMIC usage") >> Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> > > Reviewed-by: Qu Wenruo <wqu@suse.com> > >> --- >> fs/btrfs/qgroup.c | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c >> index f68b696b4bf7..42be06675c90 100644 >> --- a/fs/btrfs/qgroup.c >> +++ b/fs/btrfs/qgroup.c >> @@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info >> *fs_info, >> prealloc = kzalloc_obj(*prealloc, GFP_NOFS); >> if (!prealloc) { >> ret = -ENOMEM; >> + btrfs_abort_transaction(trans, ret); >> goto out_free_path; BTW, you are on an older branch. The latest for-next branch has the commit "btrfs: qgroup: merge error labels in btrfs_quota_enable()", which changed the branch. Next time check the MAINTAINERS file to grab the latest devel branch. >> } >> qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID); > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] btrfs: fix use-after-free on quota enable allocation failure 2026-10-07 9:17 ` Qu Wenruo 2026-10-07 9:22 ` Qu Wenruo @ 2026-10-07 9:59 ` Qu Wenruo 2026-10-07 11:55 ` Yalagada Pavan Kumar 1 sibling, 1 reply; 6+ messages in thread From: Qu Wenruo @ 2026-10-07 9:59 UTC (permalink / raw) To: pavankumaryalagada, dsterba Cc: mason, fdmanana, shuah, linux-btrfs, linux-kernel, syzbot+947286c775f432b073a8 在 2026/10/7 19:47, Qu Wenruo 写道: > > > 在 2026/10/7 19:36, pavankumaryalagada@gmail.com 写道: >> From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> >> >> The quota root remains on the transaction's dirty root list when >> kzalloc_obj() fails and btrfs_quota_enable() releases it without >> aborting the transaction. Later add_root_to_dirty_list() then accesses >> the freed dirty_list, causing a slab-use-after-free. >> >> Abort the transaction on allocation failure to clean up the dirty >> root before releasing the quota root. >> >> Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com >> Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8 >> Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to >> reduce GFP_ATOMIC usage") >> Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> > > Reviewed-by: Qu Wenruo <wqu@suse.com> My bad, Sashiko exposed a valid but very rare race that the temporary quota_root can be added to fs_info->dirty_cowonly_roots list. This requires enough subvolumes to make quota_root to be higher than level 0 in the first place, which is not common but definitely possible. Although all readers of fs_info->dirty_cowonly_roots won't be reached after the transaction is aborted, there is still a very small window that another thread is already holding a trans handler just after the transaction is aborted and the quota root is freed. In that case the other thread may access the already freed quota_root through fs_info->dirty_cowonly_roots->next. I'm afraid we need to call list_del("a_root->dirty_list) with proper trans_lock hold during error handling. > >> --- >> fs/btrfs/qgroup.c | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c >> index f68b696b4bf7..42be06675c90 100644 >> --- a/fs/btrfs/qgroup.c >> +++ b/fs/btrfs/qgroup.c >> @@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info >> *fs_info, >> prealloc = kzalloc_obj(*prealloc, GFP_NOFS); >> if (!prealloc) { >> ret = -ENOMEM; >> + btrfs_abort_transaction(trans, ret); >> goto out_free_path; >> } >> qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID); > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] btrfs: fix use-after-free on quota enable allocation failure 2026-10-07 9:59 ` Qu Wenruo @ 2026-10-07 11:55 ` Yalagada Pavan Kumar 2026-10-07 20:58 ` Qu Wenruo 0 siblings, 1 reply; 6+ messages in thread From: Yalagada Pavan Kumar @ 2026-10-07 11:55 UTC (permalink / raw) To: Qu Wenruo Cc: dsterba, mason, fdmanana, shuah, linux-btrfs, linux-kernel, syzbot+947286c775f432b073a8 On Wed, Oct 07, 2026 at 08:29:14PM +1030, Qu Wenruo wrote: > > > 在 2026/10/7 19:47, Qu Wenruo 写道: > > > > > > 在 2026/10/7 19:36, pavankumaryalagada@gmail.com 写道: > > > From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> > > > > > > The quota root remains on the transaction's dirty root list when > > > kzalloc_obj() fails and btrfs_quota_enable() releases it without > > > aborting the transaction. Later add_root_to_dirty_list() then accesses > > > the freed dirty_list, causing a slab-use-after-free. > > > > > > Abort the transaction on allocation failure to clean up the dirty > > > root before releasing the quota root. > > > > > > Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com > > > Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8 > > > Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to > > > reduce GFP_ATOMIC usage") > > > Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> > > > > Reviewed-by: Qu Wenruo <wqu@suse.com> > > My bad, Sashiko exposed a valid but very rare race that the temporary > quota_root can be added to fs_info->dirty_cowonly_roots list. > > This requires enough subvolumes to make quota_root to be higher than level 0 > in the first place, which is not common but definitely possible. > > Although all readers of fs_info->dirty_cowonly_roots won't be reached after > the transaction is aborted, there is still a very small window that another > thread is already holding a trans handler just after the transaction is > aborted and the quota root is freed. > > In that case the other thread may access the already freed quota_root > through fs_info->dirty_cowonly_roots->next. > > I'm afraid we need to call list_del("a_root->dirty_list) with proper > trans_lock hold during error handling. Thanks, Qu. I understand. I'll update the error handling to remove quota_root->dirty_list under trans_lock before dropping the quota root reference, based on the latest for-next. I'll send v2. Thanks, Pavan > > > > > --- > > > fs/btrfs/qgroup.c | 1 + > > > 1 file changed, 1 insertion(+) > > > > > > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > > > index f68b696b4bf7..42be06675c90 100644 > > > --- a/fs/btrfs/qgroup.c > > > +++ b/fs/btrfs/qgroup.c > > > @@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info > > > *fs_info, > > > prealloc = kzalloc_obj(*prealloc, GFP_NOFS); > > > if (!prealloc) { > > > ret = -ENOMEM; > > > + btrfs_abort_transaction(trans, ret); > > > goto out_free_path; > > > } > > > qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID); > > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] btrfs: fix use-after-free on quota enable allocation failure 2026-10-07 11:55 ` Yalagada Pavan Kumar @ 2026-10-07 20:58 ` Qu Wenruo 0 siblings, 0 replies; 6+ messages in thread From: Qu Wenruo @ 2026-10-07 20:58 UTC (permalink / raw) To: Yalagada Pavan Kumar, Qu Wenruo Cc: dsterba, mason, fdmanana, shuah, linux-btrfs, linux-kernel, syzbot+947286c775f432b073a8 在 2026/10/7 22:25, Yalagada Pavan Kumar 写道: > On Wed, Oct 07, 2026 at 08:29:14PM +1030, Qu Wenruo wrote: >> >> >> 在 2026/10/7 19:47, Qu Wenruo 写道: >>> >>> >>> 在 2026/10/7 19:36, pavankumaryalagada@gmail.com 写道: >>>> From: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> >>>> >>>> The quota root remains on the transaction's dirty root list when >>>> kzalloc_obj() fails and btrfs_quota_enable() releases it without >>>> aborting the transaction. Later add_root_to_dirty_list() then accesses >>>> the freed dirty_list, causing a slab-use-after-free. >>>> >>>> Abort the transaction on allocation failure to clean up the dirty >>>> root before releasing the quota root. >>>> >>>> Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com >>>> Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8 >>>> Fixes: 8d54518b5e52 ("btrfs: qgroup: pre-allocate btrfs_qgroup to >>>> reduce GFP_ATOMIC usage") >>>> Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com> >>> >>> Reviewed-by: Qu Wenruo <wqu@suse.com> >> >> My bad, Sashiko exposed a valid but very rare race that the temporary >> quota_root can be added to fs_info->dirty_cowonly_roots list. >> >> This requires enough subvolumes to make quota_root to be higher than level 0 >> in the first place, which is not common but definitely possible. >> >> Although all readers of fs_info->dirty_cowonly_roots won't be reached after >> the transaction is aborted, there is still a very small window that another >> thread is already holding a trans handler just after the transaction is >> aborted and the quota root is freed. >> >> In that case the other thread may access the already freed quota_root >> through fs_info->dirty_cowonly_roots->next. >> >> I'm afraid we need to call list_del("a_root->dirty_list) with proper >> trans_lock hold during error handling. > > Thanks, Qu. I understand. > > I'll update the error handling to remove quota_root->dirty_list under trans_lock > before dropping the quota root reference, based on the latest for-next. I'll send v2. I'm exploring the idea to put such list_del() into btrfs_put_root(), which should handle it more gracefully and cover all other situations where a new root is created and dirtied. Thanks, Qu > > Thanks, > Pavan > >>> >>>> --- >>>> fs/btrfs/qgroup.c | 1 + >>>> 1 file changed, 1 insertion(+) >>>> >>>> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c >>>> index f68b696b4bf7..42be06675c90 100644 >>>> --- a/fs/btrfs/qgroup.c >>>> +++ b/fs/btrfs/qgroup.c >>>> @@ -1204,6 +1204,7 @@ int btrfs_quota_enable(struct btrfs_fs_info >>>> *fs_info, >>>> prealloc = kzalloc_obj(*prealloc, GFP_NOFS); >>>> if (!prealloc) { >>>> ret = -ENOMEM; >>>> + btrfs_abort_transaction(trans, ret); >>>> goto out_free_path; >>>> } >>>> qgroup = add_qgroup_rb(fs_info, prealloc, BTRFS_FS_TREE_OBJECTID); >>> >> > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-07 20:58 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-07 9:06 [PATCH] btrfs: fix use-after-free on quota enable allocation failure pavankumaryalagada 2026-10-07 9:17 ` Qu Wenruo 2026-10-07 9:22 ` Qu Wenruo 2026-10-07 9:59 ` Qu Wenruo 2026-10-07 11:55 ` Yalagada Pavan Kumar 2026-10-07 20:58 ` Qu Wenruo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox