public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
@ 2026-02-25 10:35 Mark Harmstone
  2026-02-25 11:28 ` Johannes Thumshirn
  2026-02-25 15:08 ` David Sterba
  0 siblings, 2 replies; 7+ messages in thread
From: Mark Harmstone @ 2026-02-25 10:35 UTC (permalink / raw)
  To: linux-btrfs, boris; +Cc: Mark Harmstone, Chris Mason

Fix a potential segfault in balance_remap_chunks(): if we quit early
because btrfs_inc_block_group_ro() fails, all the remaining items in the
chunks list will still have their bg value set to NULL. It's thus not
safe to dereference this pointer without checking first.

Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
Reported-by: Chris Mason <clm@fb.com>
Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
Signed-off-by: Mark Harmstone <mark@harmstone.com>
---
 fs/btrfs/volumes.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e15e138c515b..18911cdd2895 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
 
 		rci = list_first_entry(chunks, struct remap_chunk_info, list);
 
-		spin_lock(&rci->bg->lock);
-		is_unused = !btrfs_is_block_group_used(rci->bg);
-		spin_unlock(&rci->bg->lock);
+		if (rci->bg) {
+			spin_lock(&rci->bg->lock);
+			is_unused = !btrfs_is_block_group_used(rci->bg);
+			spin_unlock(&rci->bg->lock);
 
-		if (is_unused)
-			btrfs_mark_bg_unused(rci->bg);
+			if (is_unused)
+				btrfs_mark_bg_unused(rci->bg);
 
-		if (rci->made_ro)
-			btrfs_dec_block_group_ro(rci->bg);
+			if (rci->made_ro)
+				btrfs_dec_block_group_ro(rci->bg);
 
-		btrfs_put_block_group(rci->bg);
+			btrfs_put_block_group(rci->bg);
+		}
 
 		list_del(&rci->list);
 		kfree(rci);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-02-25 10:35 [PATCH] btrfs: fix potential segfault in balance_remap_chunks() Mark Harmstone
@ 2026-02-25 11:28 ` Johannes Thumshirn
  2026-02-25 15:08 ` David Sterba
  1 sibling, 0 replies; 7+ messages in thread
From: Johannes Thumshirn @ 2026-02-25 11:28 UTC (permalink / raw)
  To: Mark Harmstone, linux-btrfs@vger.kernel.org, boris@bur.io; +Cc: Chris Mason

On 2/25/26 11:36 AM, Mark Harmstone wrote:
> Fix a potential segfault in balance_remap_chunks(): if we quit early
> because btrfs_inc_block_group_ro() fails, all the remaining items in the
> chunks list will still have their bg value set to NULL. It's thus not
> safe to dereference this pointer without checking first.
>
> Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
> Reported-by: Chris Mason <clm@fb.com>
> Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
> Signed-off-by: Mark Harmstone <mark@harmstone.com>
> ---
>   fs/btrfs/volumes.c | 18 ++++++++++--------
>   1 file changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index e15e138c515b..18911cdd2895 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
>   
>   		rci = list_first_entry(chunks, struct remap_chunk_info, list);
>   
> -		spin_lock(&rci->bg->lock);
> -		is_unused = !btrfs_is_block_group_used(rci->bg);
> -		spin_unlock(&rci->bg->lock);
> +		if (rci->bg) {
> +			spin_lock(&rci->bg->lock);
> +			is_unused = !btrfs_is_block_group_used(rci->bg);
> +			spin_unlock(&rci->bg->lock);
>   
> -		if (is_unused)
> -			btrfs_mark_bg_unused(rci->bg);
> +			if (is_unused)
> +				btrfs_mark_bg_unused(rci->bg);
>   
> -		if (rci->made_ro)
> -			btrfs_dec_block_group_ro(rci->bg);
> +			if (rci->made_ro)
> +				btrfs_dec_block_group_ro(rci->bg);
>   
> -		btrfs_put_block_group(rci->bg);
> +			btrfs_put_block_group(rci->bg);
> +		}
>   
>   		list_del(&rci->list);
>   		kfree(rci);

Not necessarily a hot path here, but this could be made way more 
readable if you'd have a local bg variable, sth like this:

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e15e138c515b..bf315625890d 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4285,20 +4285,24 @@ static int balance_remap_chunks(struct 
btrfs_fs_info *fs_info, struct btrfs_path
  end:
      while (!list_empty(chunks)) {
          bool is_unused;
+        struct btrfs_block_group *bg;

          rci = list_first_entry(chunks, struct remap_chunk_info, list);

-        spin_lock(&rci->bg->lock);
-        is_unused = !btrfs_is_block_group_used(rci->bg);
-        spin_unlock(&rci->bg->lock);
+        bg = rci->bg;
+        if (bg) {
+            spin_lock(&bg->lock);
+            is_unused = !btrfs_is_block_group_used(bg);
+            spin_unlock(&bg->lock);

-        if (is_unused)
-            btrfs_mark_bg_unused(rci->bg);
+            if (is_unused)
+                btrfs_mark_bg_unused(bg);

-        if (rci->made_ro)
-            btrfs_dec_block_group_ro(rci->bg);
+            if (rci->made_ro)
+                btrfs_dec_block_group_ro(bg);

-        btrfs_put_block_group(rci->bg);
+            btrfs_put_block_group(bg);
+        }

          list_del(&rci->list);
          kfree(rci);


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-02-25 10:35 [PATCH] btrfs: fix potential segfault in balance_remap_chunks() Mark Harmstone
  2026-02-25 11:28 ` Johannes Thumshirn
@ 2026-02-25 15:08 ` David Sterba
  2026-02-25 15:14   ` Johannes Thumshirn
  2026-02-25 15:17   ` Filipe Manana
  1 sibling, 2 replies; 7+ messages in thread
From: David Sterba @ 2026-02-25 15:08 UTC (permalink / raw)
  To: Mark Harmstone; +Cc: linux-btrfs, boris, Chris Mason

On Wed, Feb 25, 2026 at 10:35:31AM +0000, Mark Harmstone wrote:
> Fix a potential segfault in balance_remap_chunks(): if we quit early
> because btrfs_inc_block_group_ro() fails, all the remaining items in the
> chunks list will still have their bg value set to NULL. It's thus not
> safe to dereference this pointer without checking first.
> 
> Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
> Reported-by: Chris Mason <clm@fb.com>
> Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
> Signed-off-by: Mark Harmstone <mark@harmstone.com>
> ---
>  fs/btrfs/volumes.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index e15e138c515b..18911cdd2895 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
>  
>  		rci = list_first_entry(chunks, struct remap_chunk_info, list);
>  
> -		spin_lock(&rci->bg->lock);
> -		is_unused = !btrfs_is_block_group_used(rci->bg);
> -		spin_unlock(&rci->bg->lock);
> +		if (rci->bg) {
> +			spin_lock(&rci->bg->lock);
> +			is_unused = !btrfs_is_block_group_used(rci->bg);
> +			spin_unlock(&rci->bg->lock);
>  
> -		if (is_unused)
> -			btrfs_mark_bg_unused(rci->bg);

Not related to the patch but isn't this pattern inherently racy?

The "used" is read under lock but then btrfs_mark_bg_unused() is outside
of the lock so the status can change. This can be seen it more places,
but they seem to be related to the remap tree feature.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-02-25 15:08 ` David Sterba
@ 2026-02-25 15:14   ` Johannes Thumshirn
  2026-02-25 15:17   ` Filipe Manana
  1 sibling, 0 replies; 7+ messages in thread
From: Johannes Thumshirn @ 2026-02-25 15:14 UTC (permalink / raw)
  To: dsterba@suse.cz, Mark Harmstone
  Cc: linux-btrfs@vger.kernel.org, boris@bur.io, Chris Mason

On 2/25/26 4:10 PM, David Sterba wrote:
> On Wed, Feb 25, 2026 at 10:35:31AM +0000, Mark Harmstone wrote:
>> Fix a potential segfault in balance_remap_chunks(): if we quit early
>> because btrfs_inc_block_group_ro() fails, all the remaining items in the
>> chunks list will still have their bg value set to NULL. It's thus not
>> safe to dereference this pointer without checking first.
>>
>> Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
>> Reported-by: Chris Mason <clm@fb.com>
>> Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
>> Signed-off-by: Mark Harmstone <mark@harmstone.com>
>> ---
>>   fs/btrfs/volumes.c | 18 ++++++++++--------
>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
>> index e15e138c515b..18911cdd2895 100644
>> --- a/fs/btrfs/volumes.c
>> +++ b/fs/btrfs/volumes.c
>> @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
>>   
>>   		rci = list_first_entry(chunks, struct remap_chunk_info, list);
>>   
>> -		spin_lock(&rci->bg->lock);
>> -		is_unused = !btrfs_is_block_group_used(rci->bg);
>> -		spin_unlock(&rci->bg->lock);
>> +		if (rci->bg) {
>> +			spin_lock(&rci->bg->lock);
>> +			is_unused = !btrfs_is_block_group_used(rci->bg);
>> +			spin_unlock(&rci->bg->lock);
>>   
>> -		if (is_unused)
>> -			btrfs_mark_bg_unused(rci->bg);
> Not related to the patch but isn't this pattern inherently racy?
>
> The "used" is read under lock but then btrfs_mark_bg_unused() is outside
> of the lock so the status can change. This can be seen it more places,
> but they seem to be related to the remap tree feature.

Good catch, it is! But I /think/ it's not something to worry about (too 
much), because btrfs_delete_unused_bgs() will do checks on it's own as 
well, so if the "unused" state changes, nothing bad will happen.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-02-25 15:08 ` David Sterba
  2026-02-25 15:14   ` Johannes Thumshirn
@ 2026-02-25 15:17   ` Filipe Manana
  2026-03-09 18:00     ` Mark Harmstone
  1 sibling, 1 reply; 7+ messages in thread
From: Filipe Manana @ 2026-02-25 15:17 UTC (permalink / raw)
  To: dsterba; +Cc: Mark Harmstone, linux-btrfs, boris, Chris Mason

On Wed, Feb 25, 2026 at 3:10 PM David Sterba <dsterba@suse.cz> wrote:
>
> On Wed, Feb 25, 2026 at 10:35:31AM +0000, Mark Harmstone wrote:
> > Fix a potential segfault in balance_remap_chunks(): if we quit early
> > because btrfs_inc_block_group_ro() fails, all the remaining items in the
> > chunks list will still have their bg value set to NULL. It's thus not
> > safe to dereference this pointer without checking first.
> >
> > Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
> > Reported-by: Chris Mason <clm@fb.com>
> > Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
> > Signed-off-by: Mark Harmstone <mark@harmstone.com>
> > ---
> >  fs/btrfs/volumes.c | 18 ++++++++++--------
> >  1 file changed, 10 insertions(+), 8 deletions(-)
> >
> > diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> > index e15e138c515b..18911cdd2895 100644
> > --- a/fs/btrfs/volumes.c
> > +++ b/fs/btrfs/volumes.c
> > @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
> >
> >               rci = list_first_entry(chunks, struct remap_chunk_info, list);
> >
> > -             spin_lock(&rci->bg->lock);
> > -             is_unused = !btrfs_is_block_group_used(rci->bg);
> > -             spin_unlock(&rci->bg->lock);
> > +             if (rci->bg) {
> > +                     spin_lock(&rci->bg->lock);
> > +                     is_unused = !btrfs_is_block_group_used(rci->bg);
> > +                     spin_unlock(&rci->bg->lock);
> >
> > -             if (is_unused)
> > -                     btrfs_mark_bg_unused(rci->bg);
>
> Not related to the patch but isn't this pattern inherently racy?
>
> The "used" is read under lock but then btrfs_mark_bg_unused() is outside
> of the lock so the status can change. This can be seen it more places,
> but they seem to be related to the remap tree feature.

It's not a problem since when attempting to delete unused bgs we skip
any if they are actually used.
It's done not just for this type of race but also for the case where
after added to the unused list, it becomes used before the cleaner
kthread runs to delete unused bgs.

>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-02-25 15:17   ` Filipe Manana
@ 2026-03-09 18:00     ` Mark Harmstone
  2026-03-16  9:24       ` David Sterba
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Harmstone @ 2026-03-09 18:00 UTC (permalink / raw)
  To: Filipe Manana, dsterba, Johannes Thumshirn
  Cc: linux-btrfs, boris, Chris Mason

On 25/02/2026 3.17 pm, Filipe Manana wrote:
> On Wed, Feb 25, 2026 at 3:10 PM David Sterba <dsterba@suse.cz> wrote:
>>
>> On Wed, Feb 25, 2026 at 10:35:31AM +0000, Mark Harmstone wrote:
>>> Fix a potential segfault in balance_remap_chunks(): if we quit early
>>> because btrfs_inc_block_group_ro() fails, all the remaining items in the
>>> chunks list will still have their bg value set to NULL. It's thus not
>>> safe to dereference this pointer without checking first.
>>>
>>> Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
>>> Reported-by: Chris Mason <clm@fb.com>
>>> Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
>>> Signed-off-by: Mark Harmstone <mark@harmstone.com>
>>> ---
>>>   fs/btrfs/volumes.c | 18 ++++++++++--------
>>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
>>> index e15e138c515b..18911cdd2895 100644
>>> --- a/fs/btrfs/volumes.c
>>> +++ b/fs/btrfs/volumes.c
>>> @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
>>>
>>>                rci = list_first_entry(chunks, struct remap_chunk_info, list);
>>>
>>> -             spin_lock(&rci->bg->lock);
>>> -             is_unused = !btrfs_is_block_group_used(rci->bg);
>>> -             spin_unlock(&rci->bg->lock);
>>> +             if (rci->bg) {
>>> +                     spin_lock(&rci->bg->lock);
>>> +                     is_unused = !btrfs_is_block_group_used(rci->bg);
>>> +                     spin_unlock(&rci->bg->lock);
>>>
>>> -             if (is_unused)
>>> -                     btrfs_mark_bg_unused(rci->bg);
>>
>> Not related to the patch but isn't this pattern inherently racy?
>>
>> The "used" is read under lock but then btrfs_mark_bg_unused() is outside
>> of the lock so the status can change. This can be seen it more places,
>> but they seem to be related to the remap tree feature.
> 
> It's not a problem since when attempting to delete unused bgs we skip
> any if they are actually used.
> It's done not just for this type of race but also for the case where
> after added to the unused list, it becomes used before the cleaner
> kthread runs to delete unused bgs.

Yes, the unused list means less "these BGs are definitely unused", more 
"these BGs are worth considering as maybe unused".

Johannes, your suggestion that we add a bg variable is a good one - I'll 
send another patch doing that.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] btrfs: fix potential segfault in balance_remap_chunks()
  2026-03-09 18:00     ` Mark Harmstone
@ 2026-03-16  9:24       ` David Sterba
  0 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2026-03-16  9:24 UTC (permalink / raw)
  To: Mark Harmstone
  Cc: Filipe Manana, dsterba, Johannes Thumshirn, linux-btrfs, boris,
	Chris Mason

On Mon, Mar 09, 2026 at 06:00:30PM +0000, Mark Harmstone wrote:
> On 25/02/2026 3.17 pm, Filipe Manana wrote:
> > On Wed, Feb 25, 2026 at 3:10 PM David Sterba <dsterba@suse.cz> wrote:
> >>
> >> On Wed, Feb 25, 2026 at 10:35:31AM +0000, Mark Harmstone wrote:
> >>> Fix a potential segfault in balance_remap_chunks(): if we quit early
> >>> because btrfs_inc_block_group_ro() fails, all the remaining items in the
> >>> chunks list will still have their bg value set to NULL. It's thus not
> >>> safe to dereference this pointer without checking first.
> >>>
> >>> Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/
> >>> Reported-by: Chris Mason <clm@fb.com>
> >>> Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree")
> >>> Signed-off-by: Mark Harmstone <mark@harmstone.com>
> >>> ---
> >>>   fs/btrfs/volumes.c | 18 ++++++++++--------
> >>>   1 file changed, 10 insertions(+), 8 deletions(-)
> >>>
> >>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> >>> index e15e138c515b..18911cdd2895 100644
> >>> --- a/fs/btrfs/volumes.c
> >>> +++ b/fs/btrfs/volumes.c
> >>> @@ -4288,17 +4288,19 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path
> >>>
> >>>                rci = list_first_entry(chunks, struct remap_chunk_info, list);
> >>>
> >>> -             spin_lock(&rci->bg->lock);
> >>> -             is_unused = !btrfs_is_block_group_used(rci->bg);
> >>> -             spin_unlock(&rci->bg->lock);
> >>> +             if (rci->bg) {
> >>> +                     spin_lock(&rci->bg->lock);
> >>> +                     is_unused = !btrfs_is_block_group_used(rci->bg);
> >>> +                     spin_unlock(&rci->bg->lock);
> >>>
> >>> -             if (is_unused)
> >>> -                     btrfs_mark_bg_unused(rci->bg);
> >>
> >> Not related to the patch but isn't this pattern inherently racy?
> >>
> >> The "used" is read under lock but then btrfs_mark_bg_unused() is outside
> >> of the lock so the status can change. This can be seen it more places,
> >> but they seem to be related to the remap tree feature.
> > 
> > It's not a problem since when attempting to delete unused bgs we skip
> > any if they are actually used.
> > It's done not just for this type of race but also for the case where
> > after added to the unused list, it becomes used before the cleaner
> > kthread runs to delete unused bgs.
> 
> Yes, the unused list means less "these BGs are definitely unused", more 
> "these BGs are worth considering as maybe unused".

So if there's a question or need for clarification in a patch thread
please add it as a comment (commit updated).

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-03-16  9:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-25 10:35 [PATCH] btrfs: fix potential segfault in balance_remap_chunks() Mark Harmstone
2026-02-25 11:28 ` Johannes Thumshirn
2026-02-25 15:08 ` David Sterba
2026-02-25 15:14   ` Johannes Thumshirn
2026-02-25 15:17   ` Filipe Manana
2026-03-09 18:00     ` Mark Harmstone
2026-03-16  9:24       ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox