mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free()
@ 2026-10-16  8:55 vienna-0FFH
  2026-10-16 13:17 ` Carlos Maiolino
  2026-10-16 15:23 ` Darrick J. Wong
  0 siblings, 2 replies; 4+ messages in thread
From: vienna-0FFH @ 2026-10-16  8:55 UTC (permalink / raw)
  To: Carlos Maiolino
  Cc: linux-xfs, linux-kernel, stable, viennaoffh, syzbot+e7f24354da9f7915bc54

syzbot reported a slab-use-after-free read in xfs_defer_item_unpause()
while online repair was rebuilding a bmap btree:

  BUG: KASAN: slab-use-after-free in xfs_defer_item_unpause+0x116/0x250
  Read of size 4 at addr ffff8880132c127c by task syz.0.0/5327
  Call Trace:
   xfs_defer_item_unpause
   xrep_newbt_free+0x3fe/0x5f0
   xrep_bmap_build_new_fork+0x5a9/0x740
   xrep_bmap
   xrep_attempt
   xfs_scrub_metadata

The buggy address belongs to the object at ffff8880132c1240,
which belongs to the cache xfs_defer_pending of size 64.

xrep_newbt_add_blocks() attaches a paused EFI to the repair transaction
for each space reservation so that the blocks are reclaimed if the
system goes down before the new btree is committed.  If a later
xrep_defer_finish() fails (e.g. metadata I/O errors while staging the
new btree), xfs_defer_finish_noroll() shuts the filesystem down and
xfs_defer_cancel_list() frees all pending deferred work items, which
includes the paused EFIs referenced by resv->autoreap.

The repair then unwinds through xrep_newbt_cancel() -> xrep_newbt_free().
That function notices the shutdown and jumps to the junkit label, which
calls xfs_alloc_commit_autoreap() for each leftover reservation.  That
unpauses the deferred item through the stale pointer, causing the
use-after-free.  The report confirms this: the object was allocated by
xfs_alloc_schedule_autoreap() from xrep_newbt_add_blocks(), and freed
by xfs_defer_cancel_list() from the failing xrep_defer_finish().

Beyond the use-after-free, unpausing the deferred item is pointless
once the filesystem has been shut down: the remaining deferred work
will be cancelled when the repair transaction is torn down, and any
EFI that was committed to the log before the failure is replayed by
log recovery on the next mount.

Fix this by only unpausing the autoreap when the filesystem is not shut
down.

Fixes: 6bb9ea8ecd2c ("xfs: log EFIs for all btree blocks being used to stage a btree")
Reported-by: syzbot+e7f24354da9f7915bc54@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e7f24354da9f7915bc54
Cc: stable@vger.kernel.org
Signed-off-by: vienna-0FFH <viennaoffh@gmail.com>
---
 fs/xfs/scrub/newbt.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/scrub/newbt.c b/fs/xfs/scrub/newbt.c
index 584076b..83558fd 100644
--- a/fs/xfs/scrub/newbt.c
+++ b/fs/xfs/scrub/newbt.c
@@ -516,10 +516,15 @@ junkit:
 	/*
 	 * If we still have reservations attached to @newbt, cleanup must have
 	 * failed and the filesystem is about to go down.  Clean up the incore
-	 * reservations and try to commit to freeing the space we used.
+	 * reservations.  If the filesystem is already shut down, leave the
+	 * autoreaps alone: a failed deferred finish has freed the pending
+	 * work items they point to, and nothing will ever finish deferred
+	 * work on a dead filesystem.  Any EFI that made it to the log is
+	 * replayed by log recovery.
 	 */
 	list_for_each_entry_safe(resv, n, &xnr->resv_list, list) {
-		xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
+		if (!xfs_is_shutdown(sc->mp))
+			xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
 		list_del(&resv->list);
 		xfs_perag_put(resv->pag);
 		kfree(resv);
-- 
2.43.0


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

* Re: [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free()
  2026-10-16  8:55 [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free() vienna-0FFH
@ 2026-10-16 13:17 ` Carlos Maiolino
  2026-10-16 14:16   ` Zheng Shuhao
  2026-10-16 15:23 ` Darrick J. Wong
  1 sibling, 1 reply; 4+ messages in thread
From: Carlos Maiolino @ 2026-10-16 13:17 UTC (permalink / raw)
  To: vienna-0FFH; +Cc: linux-xfs, linux-kernel, stable, syzbot+e7f24354da9f7915bc54

On Fri, Oct 16, 2026 at 04:55:36PM +0800, vienna-0FFH wrote:
> syzbot reported a slab-use-after-free read in xfs_defer_item_unpause()
> while online repair was rebuilding a bmap btree:
> 
>   BUG: KASAN: slab-use-after-free in xfs_defer_item_unpause+0x116/0x250
>   Read of size 4 at addr ffff8880132c127c by task syz.0.0/5327
>   Call Trace:
>    xfs_defer_item_unpause
>    xrep_newbt_free+0x3fe/0x5f0
>    xrep_bmap_build_new_fork+0x5a9/0x740
>    xrep_bmap
>    xrep_attempt
>    xfs_scrub_metadata
> 
> The buggy address belongs to the object at ffff8880132c1240,
> which belongs to the cache xfs_defer_pending of size 64.
> 
> xrep_newbt_add_blocks() attaches a paused EFI to the repair transaction
> for each space reservation so that the blocks are reclaimed if the
> system goes down before the new btree is committed.  If a later
> xrep_defer_finish() fails (e.g. metadata I/O errors while staging the
> new btree), xfs_defer_finish_noroll() shuts the filesystem down and
> xfs_defer_cancel_list() frees all pending deferred work items, which
> includes the paused EFIs referenced by resv->autoreap.
> 
> The repair then unwinds through xrep_newbt_cancel() -> xrep_newbt_free().
> That function notices the shutdown and jumps to the junkit label, which
> calls xfs_alloc_commit_autoreap() for each leftover reservation.  That
> unpauses the deferred item through the stale pointer, causing the
> use-after-free.  The report confirms this: the object was allocated by
> xfs_alloc_schedule_autoreap() from xrep_newbt_add_blocks(), and freed
> by xfs_defer_cancel_list() from the failing xrep_defer_finish().
> 
> Beyond the use-after-free, unpausing the deferred item is pointless
> once the filesystem has been shut down: the remaining deferred work
> will be cancelled when the repair transaction is torn down, and any
> EFI that was committed to the log before the failure is replayed by
> log recovery on the next mount.
> 
> Fix this by only unpausing the autoreap when the filesystem is not shut
> down.
> 
> Fixes: 6bb9ea8ecd2c ("xfs: log EFIs for all btree blocks being used to stage a btree")
> Reported-by: syzbot+e7f24354da9f7915bc54@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=e7f24354da9f7915bc54
> Cc: stable@vger.kernel.org
> Signed-off-by: vienna-0FFH <viennaoffh@gmail.com>

From Documentation/process/submitting-patches.rst:

"using a known identity (sorry, no anonymous contributions.)"

> ---
>  fs/xfs/scrub/newbt.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/xfs/scrub/newbt.c b/fs/xfs/scrub/newbt.c
> index 584076b..83558fd 100644
> --- a/fs/xfs/scrub/newbt.c
> +++ b/fs/xfs/scrub/newbt.c
> @@ -516,10 +516,15 @@ junkit:
>  	/*
>  	 * If we still have reservations attached to @newbt, cleanup must have
>  	 * failed and the filesystem is about to go down.  Clean up the incore
> -	 * reservations and try to commit to freeing the space we used.
> +	 * reservations.  If the filesystem is already shut down, leave the
> +	 * autoreaps alone: a failed deferred finish has freed the pending
> +	 * work items they point to, and nothing will ever finish deferred
> +	 * work on a dead filesystem.  Any EFI that made it to the log is
> +	 * replayed by log recovery.
>  	 */
>  	list_for_each_entry_safe(resv, n, &xnr->resv_list, list) {
> -		xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
> +		if (!xfs_is_shutdown(sc->mp))
> +			xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
>  		list_del(&resv->list);
>  		xfs_perag_put(resv->pag);
>  		kfree(resv);
> -- 
> 2.43.0
> 
> 

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

* Re: [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free()
  2026-10-16 13:17 ` Carlos Maiolino
@ 2026-10-16 14:16   ` Zheng Shuhao
  0 siblings, 0 replies; 4+ messages in thread
From: Zheng Shuhao @ 2026-10-16 14:16 UTC (permalink / raw)
  To: Carlos Maiolino
  Cc: linux-xfs, linux-kernel, stable, syzbot+e7f24354da9f7915bc54

Hi Carlos,

Thank you for the pointer, and my apologies for the confusion. This is
my first patch submission to the Linux kernel, and I was not aware of the
known-identity requirement for patch authorship and Signed-off-by.
Understood now; I will use my real name for all future submissions:

    Zheng Shuhao <viennaoffh@gmail.com>

(vienna-0FFH was my GitHub handle only.)

For reference, this is the testing I did on the patch before posting:

 * Built the patched tree with KASAN + XFS_DEBUG enabled; checkpatch.pl
   --strict reports 0 errors and 0 warnings.
 * Reproduced the use-after-free deterministically in QEMU on an
   unpatched kernel; the KASAN splat matches the syzbot report exactly
   (xfs_defer_item_unpause <- xrep_newbt_free <- xrep_bmap_build_new_fork,
   and the xfs_defer_pending object is freed by xfs_defer_finish_noroll).
 * With the patch applied, the same trigger produces no KASAN report: the
   scrub ioctl just returns -EIO and the shutdown path unwinds cleanly.
 * Regression runs on the patched kernel: all metadata scrub types,
   invalid scrub inputs (bad flags/generation/agno/type), and forced bmap
   btree rebuilds from 5 up to 1500 extents (covering both extents- and
   btree-format forks), with read-back verification of the files. No
   regressions; normal scrub/repair paths still succeed.

I can share the reproducer and test scripts if that is useful.

Would you prefer that I resend this as v2 with the correct
From:/Signed-off-by: lines, or can you fix up the authorship when
applying? Either way works for me.

Thanks,
Zheng Shuhao

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

* Re: [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free()
  2026-10-16  8:55 [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free() vienna-0FFH
  2026-10-16 13:17 ` Carlos Maiolino
@ 2026-10-16 15:23 ` Darrick J. Wong
  1 sibling, 0 replies; 4+ messages in thread
From: Darrick J. Wong @ 2026-10-16 15:23 UTC (permalink / raw)
  To: vienna-0FFH
  Cc: Carlos Maiolino, linux-xfs, linux-kernel, stable,
	syzbot+e7f24354da9f7915bc54

On Fri, Oct 16, 2026 at 04:55:36PM +0800, vienna-0FFH wrote:
> syzbot reported a slab-use-after-free read in xfs_defer_item_unpause()
> while online repair was rebuilding a bmap btree:
> 
>   BUG: KASAN: slab-use-after-free in xfs_defer_item_unpause+0x116/0x250
>   Read of size 4 at addr ffff8880132c127c by task syz.0.0/5327
>   Call Trace:
>    xfs_defer_item_unpause
>    xrep_newbt_free+0x3fe/0x5f0
>    xrep_bmap_build_new_fork+0x5a9/0x740
>    xrep_bmap
>    xrep_attempt
>    xfs_scrub_metadata
> 
> The buggy address belongs to the object at ffff8880132c1240,
> which belongs to the cache xfs_defer_pending of size 64.
> 
> xrep_newbt_add_blocks() attaches a paused EFI to the repair transaction
> for each space reservation so that the blocks are reclaimed if the
> system goes down before the new btree is committed.  If a later
> xrep_defer_finish() fails (e.g. metadata I/O errors while staging the
> new btree), xfs_defer_finish_noroll() shuts the filesystem down and
> xfs_defer_cancel_list() frees all pending deferred work items, which
> includes the paused EFIs referenced by resv->autoreap.
> 
> The repair then unwinds through xrep_newbt_cancel() -> xrep_newbt_free().
> That function notices the shutdown and jumps to the junkit label, which
> calls xfs_alloc_commit_autoreap() for each leftover reservation.  That
> unpauses the deferred item through the stale pointer, causing the
> use-after-free.  The report confirms this: the object was allocated by
> xfs_alloc_schedule_autoreap() from xrep_newbt_add_blocks(), and freed
> by xfs_defer_cancel_list() from the failing xrep_defer_finish().
> 
> Beyond the use-after-free, unpausing the deferred item is pointless
> once the filesystem has been shut down: the remaining deferred work
> will be cancelled when the repair transaction is torn down, and any
> EFI that was committed to the log before the failure is replayed by
> log recovery on the next mount.
> 
> Fix this by only unpausing the autoreap when the filesystem is not shut
> down.
> 
> Fixes: 6bb9ea8ecd2c ("xfs: log EFIs for all btree blocks being used to stage a btree")
> Reported-by: syzbot+e7f24354da9f7915bc54@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=e7f24354da9f7915bc54
> Cc: stable@vger.kernel.org
> Signed-off-by: vienna-0FFH <viennaoffh@gmail.com>
> ---
>  fs/xfs/scrub/newbt.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/xfs/scrub/newbt.c b/fs/xfs/scrub/newbt.c
> index 584076b..83558fd 100644
> --- a/fs/xfs/scrub/newbt.c
> +++ b/fs/xfs/scrub/newbt.c
> @@ -516,10 +516,15 @@ junkit:
>  	/*
>  	 * If we still have reservations attached to @newbt, cleanup must have
>  	 * failed and the filesystem is about to go down.  Clean up the incore
> -	 * reservations and try to commit to freeing the space we used.
> +	 * reservations.  If the filesystem is already shut down, leave the
> +	 * autoreaps alone: a failed deferred finish has freed the pending
> +	 * work items they point to, and nothing will ever finish deferred
> +	 * work on a dead filesystem.  Any EFI that made it to the log is
> +	 * replayed by log recovery.
>  	 */
>  	list_for_each_entry_safe(resv, n, &xnr->resv_list, list) {
> -		xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
> +		if (!xfs_is_shutdown(sc->mp))

What if some other thread initiates the shutdown?

--D

> +			xfs_alloc_commit_autoreap(sc->tp, &resv->autoreap);
>  		list_del(&resv->list);
>  		xfs_perag_put(resv->pag);
>  		kfree(resv);
> -- 
> 2.43.0
> 
> 

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

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

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16  8:55 [PATCH] xfs: fix slab-use-after-free in xrep_newbt_free() vienna-0FFH
2026-10-16 13:17 ` Carlos Maiolino
2026-10-16 14:16   ` Zheng Shuhao
2026-10-16 15:23 ` Darrick J. Wong

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

all inboxes | Powered by JetHome®