Linux XFS filesystem development
 help / color / mirror / Atom feed
* [PATCH] xfs: validate recovered buffer item dirty bitmaps
@ 2026-06-11 21:23 Kyle Zeng
  2026-06-16 17:03 ` Brian Foster
  0 siblings, 1 reply; 2+ messages in thread
From: Kyle Zeng @ 2026-06-11 21:23 UTC (permalink / raw)
  To: linux-xfs; +Cc: Carlos Maiolino, outbounddisclosures, Kyle Zeng

XFS buffer log recovery trusts the dirty bitmap in recovered buffer log
items when replaying logged regions into the buffer.  The replay path only
has debug assertions to check that each bitmap extent fits within the
buffer described by blf_len.

A corrupted log can therefore set a dirty bit beyond the end of the
recovered buffer.  In non-debug builds, xlog_recover_do_reg_buffer() will
copy the corresponding logged region to that out-of-range buffer offset.

Validate the recovered dirty bitmap and the associated logged data regions
before replay.  Reject buffer items whose dirty extents extend beyond
blf_len, whose region count does not match the bitmap, or whose data iovecs
are malformed.

Assisted-by: Codex:gpt-5.5
Signed-off-by: Kyle Zeng <kylebot@openai.com>
---
 fs/xfs/xfs_buf_item_recover.c | 63 +++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c
index 02b95b89d1b5..576d6245e922 100644
--- a/fs/xfs/xfs_buf_item_recover.c
+++ b/fs/xfs/xfs_buf_item_recover.c
@@ -206,6 +206,63 @@ xlog_recover_buf_commit_pass1(
 	return 0;
 }
 
+/*
+ * Make sure the recovered dirty bitmap only describes ranges inside the
+ * recovered buffer and that each logged region is backed by one data iovec.
+ */
+STATIC int xlog_recover_validate_buf_data_map(struct xfs_mount *mp,
+					      struct xlog_recover_item *item,
+					      struct xfs_buf_log_format *buf_f)
+{
+	u64				buf_bytes = BBTOB(buf_f->blf_len);
+	int				i = 1;
+	int				bit = 0;
+
+	while (1) {
+		u64			reg_bytes;
+		u64			reg_end;
+		int			nbits;
+
+		bit = xfs_next_bit(buf_f->blf_data_map, buf_f->blf_map_size,
+				   bit);
+		if (bit == -1)
+			break;
+
+		nbits = xfs_contig_bits(buf_f->blf_data_map,
+					buf_f->blf_map_size, bit);
+		if (XFS_IS_CORRUPT(mp, nbits <= 0))
+			return -EFSCORRUPTED;
+
+		reg_bytes = (u64)nbits << XFS_BLF_SHIFT;
+		reg_end = ((u64)bit << XFS_BLF_SHIFT) + reg_bytes;
+		if (XFS_IS_CORRUPT(mp, reg_end > buf_bytes))
+			return -EFSCORRUPTED;
+
+		if (XFS_IS_CORRUPT(mp, i >= item->ri_total))
+			return -EFSCORRUPTED;
+		if (XFS_IS_CORRUPT(mp, !item->ri_buf[i].iov_base))
+			return -EFSCORRUPTED;
+		if (XFS_IS_CORRUPT(mp, item->ri_buf[i].iov_len == 0 ||
+				   item->ri_buf[i].iov_len % XFS_BLF_CHUNK))
+			return -EFSCORRUPTED;
+		if (XFS_IS_CORRUPT(mp, item->ri_buf[i].iov_len > reg_bytes))
+			return -EFSCORRUPTED;
+
+		/*
+		 * A single contiguous dirty range can be split into multiple
+		 * log vectors.  Advance by the amount covered by this iovec.
+		 */
+		nbits = item->ri_buf[i].iov_len >> XFS_BLF_SHIFT;
+		i++;
+		bit += nbits;
+	}
+
+	if (XFS_IS_CORRUPT(mp, i != item->ri_total))
+		return -EFSCORRUPTED;
+
+	return 0;
+}
+
 /*
  * Validate the recovered buffer is of the correct type and attach the
  * appropriate buffer operations to them for writeback. Magic numbers are in a
@@ -1033,6 +1090,12 @@ xlog_recover_buf_commit_pass2(
 			goto cancelled;
 	}
 
+	error = xlog_recover_validate_buf_data_map(mp, item, buf_f);
+	if (error) {
+		ASSERT(error == -EFSCORRUPTED);
+		return error;
+	}
+
 	trace_xfs_log_recover_buf_recover(log, buf_f);
 	error = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len,
 			  0, &bp, NULL);
-- 
2.43.0

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

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

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-11 21:23 [PATCH] xfs: validate recovered buffer item dirty bitmaps Kyle Zeng
2026-06-16 17:03 ` Brian Foster

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