Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Eduard Zateev <hackerowskiy@gmail.com>
To: hackerowskiy@gmail.com
Cc: "Darrick J. Wong" <djwong@kernel.org>,
	stable@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
	Carlos Maiolino <cem@kernel.org>
Subject: [PATCH 23/26] xfs: fix cursor and pointer handling when recovering iunlink buckets
Date: Tue, 22 Sep 2026 13:02:18 +0200	[thread overview]
Message-ID: <20260922110221.1431-23-hackerowskiy@gmail.com> (raw)
In-Reply-To: <20260922110221.1431-1-hackerowskiy@gmail.com>

From: "Darrick J. Wong" <djwong@kernel.org>

LOLLM pointed out a bug in xlog_recover_iunlink_bucket:

1. We don't null out prev_ip after releasing it, which can lead to UAF
   problems if the inodegc flush call in the loop fails.

at which point I noticed even more bugs:

2. If the inodegc flush inside the loop fails, we also leak @ip.

3. We set prev_agino to agino having already advanced agino, which
   results in inodes with i_prev_unlinked set to itself.

4. If we exit the bottom of the loop with prev_ip set, then prev_ip
   aliases ip and we also set its i_prev_unlinked to itself.

Bugs 3 and 4 introduce loops into the unlinked list, though these loops
don't surface because we immediately flush each unlinked inode after
loading it.

Fix all of these issues.

Cc: stable@vger.kernel.org # v6.0
Fixes: 04755d2e5821b3 ("xfs: refactor xlog_recover_process_iunlinks()")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
 fs/xfs/xfs_log_recover.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index e7e49529658b..cf0d610265fe 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2736,12 +2736,13 @@ xlog_recover_iunlink_bucket(
 {
 	struct xfs_mount	*mp = pag_mount(pag);
 	struct xfs_inode	*prev_ip = NULL;
-	struct xfs_inode	*ip;
 	xfs_agino_t		prev_agino, agino;
 	int			error = 0;
 
 	agino = be32_to_cpu(agi->agi_unlinked[bucket]);
 	while (agino != NULLAGINO) {
+		struct xfs_inode	*ip;
+
 		error = xfs_iget(mp, NULL, xfs_agino_to_ino(pag, agino), 0, 0,
 				&ip);
 		if (error)
@@ -2750,11 +2751,11 @@ xlog_recover_iunlink_bucket(
 		ASSERT(VFS_I(ip)->i_nlink == 0);
 		ASSERT(VFS_I(ip)->i_mode != 0);
 		xfs_iflags_clear(ip, XFS_IRECOVERY);
-		agino = ip->i_next_unlinked;
 
 		if (prev_ip) {
 			ip->i_prev_unlinked = prev_agino;
 			xfs_irele(prev_ip);
+			prev_ip = NULL;
 
 			/*
 			 * Ensure the inode is removed from the unlinked list
@@ -2766,18 +2767,20 @@ xlog_recover_iunlink_bucket(
 			 * complete.
 			 */
 			error = xfs_inodegc_flush(mp);
-			if (error)
-				break;
+			if (error) {
+				xfs_irele(ip);
+				return error;
+			}
 		}
 
 		prev_agino = agino;
+		agino = ip->i_next_unlinked;
 		prev_ip = ip;
 	}
 
 	if (prev_ip) {
 		int	error2;
 
-		ip->i_prev_unlinked = prev_agino;
 		xfs_irele(prev_ip);
 
 		error2 = xfs_inodegc_flush(mp);
-- 
2.55.0


  parent reply	other threads:[~2026-09-22 11:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260922110221.1431-1-hackerowskiy@gmail.com>
2026-09-22 11:01 ` [PATCH 02/26] xfs: don't assert when XFS_SCRUB_TYPE_HEALTHY scans return corruption Eduard Zateev
2026-09-22 11:01 ` [PATCH 03/26] xfs: fix attr fork block count checks in xrep_inode_blockcounts Eduard Zateev
2026-09-22 11:01 ` [PATCH 04/26] xfs: release orphanage dir inode if chown fails Eduard Zateev
2026-09-22 11:02 ` [PATCH 06/26] xfs: use correct jiffies comparison function in xchk_maybe_relax Eduard Zateev
2026-09-22 11:02 ` [PATCH 07/26] xfs: check padding field in xfs_ioc_commit_range Eduard Zateev
2026-09-22 11:02 ` [PATCH 08/26] xfs: don't call xfs_exchange_range_finish for a dry run Eduard Zateev
2026-09-22 11:02 ` [PATCH 09/26] xfs: use the correct reservations for rtrmap/refcount recovery Eduard Zateev
2026-09-22 11:02 ` [PATCH 11/26] xfs: only flag zero padding for dir3 data blocks, not dir3 block blocks Eduard Zateev
2026-09-22 11:02 ` [PATCH 12/26] xfs: check di_forkoff correctly in scrub Eduard Zateev
2026-09-22 11:02 ` [PATCH 17/26] xfs: call xfs_dquot_set_prealloc_limits if we installed default rtb limits Eduard Zateev
2026-09-22 11:02 ` [PATCH 18/26] xfs: fix rtgroup repair estimations Eduard Zateev
2026-09-22 11:02 ` [PATCH 19/26] xfs: don't cross reference rmapbt with bitmaps if they're incomplete Eduard Zateev
2026-09-22 11:02 ` [PATCH 20/26] xfs: don't let memory failures leak blocks and kill repairs Eduard Zateev
2026-09-22 11:02 ` [PATCH 21/26] xfs: don't merge different file IO error types Eduard Zateev
2026-09-22 11:02 ` [PATCH 22/26] xfs: fix blockgc group quota scanning when usrquota isn't enforced Eduard Zateev
2026-09-22 11:02 ` Eduard Zateev [this message]
2026-09-22 11:02 ` [PATCH 24/26] xfs: drop dquot flush lock when we can't find a buffer to flush Eduard Zateev
2026-09-22 11:02 ` [PATCH 25/26] xfs: don't let hidden_space go negative in xfs_metafile_resv_init Eduard Zateev
2026-09-22 11:02 ` [PATCH 26/26] xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots Eduard Zateev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260922110221.1431-23-hackerowskiy@gmail.com \
    --to=hackerowskiy@gmail.com \
    --cc=cem@kernel.org \
    --cc=djwong@kernel.org \
    --cc=hch@lst.de \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox