Commit graph

1,461,791 commits

Author SHA1 Message Date
Hongling Zeng
b7eea80be2 xfs: validate attr entry pointer before field access
xfs_attr3_leaf_verify_entry() accesses lentry/rentry fields (namelen,
valuelen) before checking if the entry pointer itself is within bounds.
If nameidx is crafted to point near the end of the buffer, these field
accesses can read out-of-bounds before the bounds check at
name_end > buf_end is performed.

Add explicit bounds checks for entry pointers before accessing their
fields. Use offsetof() to check that the start of the flexible array
member (nameval/name) is within bounds, which ensures all preceding
fields are safe to access.

Fixes: c84760659d ("xfs: check attribute leaf block structure")
Cc: <stable@vger.kernel.org> # v5.5
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:51:30 +02:00
Hongling Zeng
6e6a314014 xfs: check split_sectors validity before bio_split call
Change the split_sectors check from !split_sectors to split_sectors <= 0
to make the error handling explicit. While bio_split_rw_at() cannot return
a negative error code for the current GC I/O path (GC I/O doesn't use
REQ_ATOMIC/REQ_NOWAIT flags and has proper alignment), making the check
explicit improves code clarity and makes the intent clear.

This also makes the code more robust for future maintenance if different
I/O patterns are introduced.

Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:47:03 +02:00
Hongling Zeng
a94e648f03 xfs: use file target for post-log fsync fallback flush
xfs_file_fsync() has a fallback flush for the case where the log force
was a no-op, for example fdatasync/O_DSYNC writes that do not require
metadata updates. The current fallback path is expressed in terms of the
main data device and explicitly excludes realtime inodes.

Realtime files with a separate realtime device are flushed before the log
force, because their data must reach stable storage before the log commit.
For the internal realtime device used by the zoned allocator, writes are
out-of-place and update inode and bmap metadata from I/O completion, so
the overwrite-without-metadata-update case does not apply in the same way.

Even so, the current fallback condition is inconsistent because it is
expressed as "non-realtime inode on the main data device" rather than in
terms of the inode's actual file data target.

Use xfs_inode_buftarg() to obtain the target that stores this file's
data, and issue the fallback flush when the log force did not flush
anything and the log target is the same as that file target.

This preserves existing behavior for regular files while making the
fallback logic consistent for files whose data target is selected by the
inode.

Fixes: bdc03eb5f9 ("xfs: allow internal RT devices for zoned mode")
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
Suggested-by: Christoph Hellwig <hch@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:45:28 +02:00
Yun Zhou
0241ea5fb0 xfs: restore nofs context unconditionally in xfs_trans_roll
When __xfs_trans_commit() fails in xfs_trans_roll(), the NOFS context
is cleared but only restored in the success path.  This leaves the
error path without nofs protection, causing a circular lock dependency
between xfs_nondir_ilock_class and fs_reclaim:

       CPU0                    CPU1
       ----                    ----
  lock(&xfs_nondir_ilock_class);
                               lock(fs_reclaim);
                               lock(&xfs_nondir_ilock_class);
  lock(fs_reclaim);

Fix this by moving xfs_trans_set_context() before the error check so
that nofs context is always restored on the new transaction.

Reported-by: syzbot+59178abfeb0ea3f0ab20@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=59178abfeb0ea3f0ab20
Fixes: a1ca658d64 ("xfs: fix incorrect context handling in xfs_trans_roll")
Cc: stable@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:43:56 +02:00
Christoph Hellwig
00f40876f4 xfs: add lockless xfs_buf_readahead_map fast path
Readahead currently always locks the buffer, which can cause contention
with actual users of the buffer.  Add a fast path without taking any
locks if the buffer is uptodate and not stale.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:44 +02:00
Christoph Hellwig
2aedf844be xfs: move buffer locking out of xfs_find_get_buf
To prepare for buffer loookups that don't lock the buffer, move the
call to xfs_buf_find_lock from xfs_find_get_buf to its callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
21cc7775ee xfs: merge xfs_buf_reverify into xfs_buf_read_map
xfs_buf_read_map is the only caller of xfs_buf_reverify that is left.
Merge it into that so that the comments can be moved closer to the
logic, and redundant asserts can be removed.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
819f1cc98a xfs: use goto based error unwinding in xfs_buf_read_map
This keeps the I/O error handling contained at the end of the function
and removes the indentation for it.  It also allows to reorder the
comments so that they are closer to the logic that they describe.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
3d10272743 xfs: don't reverify buffers in xfs_buf_readahead_map
xfs_buf_read_map calls xfs_buf_reverify to ensure the verifier has run
for a buffer before the data can be used when an earlier readahead read
the data before the buf_ops were assigned.

There is no point in doing this in xfs_buf_readahead_map for a buffer
already in memory as a later xfs_buf_read will do the same and can
actually propagate the error to the caller.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
b15f6520ab xfs: use WRITE_ONCE to update b_flags
Prepare for limited lockless reading of flags by using WRITE_ONCE to
prevent the compiler from doing non-standard read-modify-write
operations.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
9f224de410 xfs: hide b_flags manipulation from code outside of xfs_buf.c
Add helpers for the remaining buffer flags manipulation not done in the
core buffer cache code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
d80fe85bb2 xfs: remove _XBF_LOGRECOVERY
Adding _XBF_LOGRECOVERY to every buffer write from log recovery is error
prone.  Instead key off the behavior on log recovery being active with
indirecting that through a flag.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
7a4eae80b5 xfs: remove spurious XBF_DONE clearing on readahead validation failure
Both callers of ->verify_read already do this, so don't duplicate the
flag manipulation.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
b6ba780af0 xfs: split out a lower-level xfs_buf_get_map helper from xfs_find_get_buf
xfs_buf_get_map is currently reused to implement xfs_buf_read_map and
xfs_buf_readahead_map.  This causes double accounting of buf_get stat
and leads to some ugly overload of the flags.

Split out a slightly lower-level xfs_find_get_buf helper and use that to
implement xfs_buf_get_map, xfs_buf_read_map and xfs_buf_readahead_map.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
568c8798a3 xfs: consolidate buffer locking in xfs_buf_get_map
Consolidate the code to lock the buffer based on the passed in flags
into xfs_buf_get_map instead of having two different sites for buffer
lookup vs insertation.  This requires initializing b_lock to unlocked on
allocation and doing an atomic for locking it for newly allocated buffers,
but greatly simplifies the logic.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Christoph Hellwig
45fd506c33 xfs: don't get a pag reference in xfs_buf_get_map
As of commit 497560b9ef ("xfs: switch (back) to a per-buftarg buffer
hash"), buffer lookups don't require the perag structure.  Stop looking
it up in xfs_buf_get_map, and instead only find it when allocating a new
buffer.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-08-10 08:34:43 +02:00
Cihan Karadag
56aa9ef3c4 xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int
Convert open-coded kmalloc() multiplication to the modern kmalloc_objs()
interface to improve type safety and prevent potential integer
overflows.

No functional changes are intended.

Signed-off-by: Cihan Karadag <cihan.cihan@gmail.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:11 +02:00
Johannes Thumshirn
c6c54d05b1 xfs: mark internal metadir file creation helpers static
Now that there is xfs_metadir_create_file() mark
xfs_metadir_start_create(), xfs_metadir_create() and xfs_metadir_cancel()
as static and remove them from xfs_metadir.h.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:11 +02:00
Johannes Thumshirn
de64b150a7 xfs: create rtgroup metadir inodes using xfs_metadir_create_file
Now that we have xfs_metadir_create_file() use it in
xfs_rtginode_create().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:10 +02:00
Johannes Thumshirn
e6ecb1a98d xfs: create quota metadir inodes using xfs_metadir_create_file
Now that we have xfs_metadir_create_file() use it in
xfs_dqinode_metadir_create().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:10 +02:00
Johannes Thumshirn
daf43402da xfs: add xfs_metadir_create_file helper
Factor the metadata inode create/commit/cleanup lifecycle out of
xfs_metadir_mkdir into a reusable helper that takes an optional callback
to initialize the new inode, and convert xfs_metadir_mkdir to it.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:10 +02:00
Pankaj Raghav
b16b63a479 xfs: add support for FALLOC_FL_WRITE_ZEROES
If the underlying block device supports the unmap write zeroes
operation, this flag allows users to quickly preallocate a file with
written extents that contain zeroes. This is beneficial for subsequent
overwrites as it prevents the need for unwritten-to-written extent
conversions, thereby significantly reducing metadata updates and journal
I/O overhead, improving overwrite performance.

Punch the range first so it becomes a hole, update the size via
xfs_falloc_setsize() while it is still a hole (so its xfs_zero_range()
skips it and avoids rezeroing), then convert it to written
zeroed extents. A crash between the size update and the conversion is
safe, as a hole within i_size reads back as zeroes.

Co-developed-by: Lukas Herbolt <lukas@herbolt.com>
Signed-off-by: Lukas Herbolt <lukas@herbolt.com>
Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:10 +02:00
Pankaj Raghav
86e332447d xfs: add an allocation mode to xfs_alloc_file_space()
xfs_alloc_file_space() hardcodes XFS_BMAPI_PREALLOC to preallocate
unwritten extents across a range.

In preparation for FALLOC_FL_WRITE_ZEROES, add an explicit allocation
mode argument, enum xfs_alloc_file_space_mode, and derive the xfs_bmapi
flags from it. The only mode for now is XFS_ALLOC_FILE_SPACE_PREALLOC,
which preallocates unwritten extents and marks the inode as preallocated
exactly as before, so there is no functional change.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:12:10 +02:00
Darrick J. Wong
b28d23c516 xfs: mark nonzero sb_gquotino as corrupt on metadir filesystems
On a metadir filesystem, the superblock gquotino field is always zero
because we find the quota inodes through the metadata directory tree.
A nonzero value is therefore a corruption (as pointed out by LOLLM) so
mark the failure as such.

Cc: stable@vger.kernel.org # v6.13
Fixes: 06b20ef09b ("xfs: check pre-metadir fields correctly")
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>
2026-07-22 15:06:25 +02:00
Darrick J. Wong
49933254ba xfs: zero i_nlink before repair puts inode on unlinked list
LOLLM observes that we don't reset i_nlink if we encounter a file with
no parent that isn't on the unlinked list.  This causes unnecessary
assertion trips on debugging kernels and an inconsistent file, so let's
fix that.

Cc: stable@vger.kernel.org # v6.10
Fixes: 669dfe883c ("xfs: update the unlinked list when repairing link counts")
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>
2026-07-22 15:06:25 +02:00
Darrick J. Wong
8ed7810472 xfs: rtsummary scrub should treat rtbitmap corruption errors as an xref error
LOLLM notes the discrepancy between the comment saying that this is an
xref error and the code, which marks a (non-xref) corruption error.
This appears to be a regression.

Cc: stable@vger.kernel.org # v6.13
Fixes: e3088ae2dc ("xfs: move RT bitmap and summary information to the rtgroup")
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>
2026-07-22 15:06:25 +02:00
Darrick J. Wong
61606f8846 xfs: fix transaction block reservation in xrep_rtbitmap
LOLLM pointed out an inconsistency in the block reservation code in
xrep_rtbitmap.  The first is that the reservation computation is not
consistent between the code that sets up the repair and the code that
tries to avoid exceeding the transaction reservation once we know how
big the rtbitmap really must be.  As a result, the logic doesn't work.

In fixing that, a second problem emerges: if we do readjust, we ask for
the entire reservation all over again.  We really only need the delta,
so ask only for that.

Fix all these problems by hoisting the computation to a trivial helper
so that it gets used in both places.

Cc: stable@vger.kernel.org # v6.14
Fixes: 8defee8dff ("xfs: online repair of realtime bitmaps for a realtime group")
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>
2026-07-22 15:06:24 +02:00
Darrick J. Wong
270ffcd9b0 xfs: check cowextsize in xrep_inode_cowextsize
LOLLM points out that the function that corrects cowextsize should check
i_cowextsize, not i_extsize.

Cc: stable@vger.kernel.org # v6.14
Fixes: a9600db96f ("xfs: detect and repair misaligned rtinherit directory cowextsize hints")
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>
2026-07-22 15:06:24 +02:00
Christoph Hellwig
7aa67044e7 xfs: update BDI {io,ra}_pages values based on the RT device limits
When using XFS with a main device on an SSD that stores metadata and a RT
device to store data on a HDD, we fail to take the I/O sizes for the RT
device into accounting, leading to up to 5% slower read performance when
using an SSD for metadata vs storing data and metadata on the HDD.

Fix this up by taking the RT settings into account at mount an restoring
the old settings at unmount time, unless the BDI settings have changed
from those set by XFS.

Reported-by: Filip Blagojevic <filip.blagojevic@wdc.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:06:24 +02:00
Yun Zhou
d852729c5f xfs: handle NULL b_addr in xfs_buf_free
When xfs_buf_alloc_backing_mem() fails, xfs_buf_free() is called with
bp->b_addr still NULL.  The code falls through to the folio_put path
which calls virt_to_folio(NULL), dereferencing an invalid address and
causing a kernel crash.

 Call Trace:
  xfs_buf_free+0x25f/0x510
  xfs_buf_alloc+0xc98/0x19b0
  xfs_buf_find_insert+0x55/0x14d0
  xfs_buf_get_map+0x122b/0x17c0
  xfbtree_init_leaf_block+0x11c/0x4a0
  xfbtree_init+0x1bb/0x460
  xrep_rmap_setup_scan+0x100/0x1f0
  xrep_rmapbt+0x41/0xc0

Fix this by skipping folio_put() when bp->b_addr is NULL.

Fixes: 5076a6040c ("xfs: support in-memory buffer cache targets")
Reported-by: syzbot+94c22d92f72f5a235b7d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=94c22d92f72f5a235b7d
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:06:24 +02:00
Ibrahim Hashimov
813f8136a2 xfs: bounds-check buffer log item's dirty bitmap
xlog_recover_do_reg_buffer() replays each dirty region described by a
buffer log item's bitmap into the buffer read for that item:

	memcpy(xfs_buf_offset(bp, (uint)bit << XFS_BLF_SHIFT),
		item->ri_buf[i].iov_base,
		nbits << XFS_BLF_SHIFT);

The destination offset (bit/nbits, from the logged dirty bitmap) and the
buffer size (from the logged blf_len) are both attacker-controlled and
otherwise unrelated, yet the only thing bounding the copy is an ASSERT(),
which compiles away on production kernels. A crafted image logging a
small blf_len together with a bitmap bit past the end of that buffer
drives the memcpy() past the buffer's allocation, corrupting adjacent
kernel heap during mount-time log recovery. This is reachable by anyone
who can get a crafted image mounted -- the malicious-filesystem threat
model XFS already guards against elsewhere.

Turn the ASSERT() into a real XFS_IS_CORRUPT() check that aborts recovery
of the buffer with -EFSCORRUPTED, consistent with the validate-and-fail
idiom already used in xlog_recover_do_inode_buffer() and
xfs_dquot_item_recover.c. xlog_recover_do_reg_buffer() therefore becomes
STATIC int and its three callers propagate the error.

Found and confirmed with KASAN on a CONFIG_XFS_DEBUG=n build: the crafted
image trips a slab-out-of-bounds write before this change and fails
recovery cleanly with -EFSCORRUPTED after it.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:06:24 +02:00
Xiang Mei
cc3144da37 xfs: fix off-by-one in rtrefcount btree root level validation
xfs_rtrefcountbt_compute_maxlevels() sets

	mp->m_rtrefc_maxlevels = min(d_maxlevels, r_maxlevels) + 1;

where the trailing "+ 1" already accounts for the inode-root level, so the
deepest valid on-disk root level is m_rtrefc_maxlevels - 1 and a cursor must
satisfy bc_nlevels <= bc_maxlevels (= m_rtrefc_maxlevels).

The two on-disk validation paths, xfs_rtrefcountbt_verify() and
xfs_iformat_rtrefcount(), check the root level with ">" instead of ">=", so a
crafted rtreflink (metadir + realtime + reflink) image whose
/rtgroups/N.refcount inode has bb_level == m_rtrefc_maxlevels is accepted on
mount. xfs_rtrefcountbt_init_cursor() then sets bc_nlevels = bb_level + 1,
exceeding bc_maxlevels by one. Since the xfs_rtrefcountbt_cur slab object is
sized for exactly bc_maxlevels entries, the first btree op on such a cursor
indexes bc_levels[m_rtrefc_maxlevels] past the end of the object. This is
reached by the first rtrefcount cursor built after mount, via log/CoW
recovery (xfs_reflink_recover_cow() during xfs_mountfs()) or an
FS_IOC_GETFSMAP over the realtime device.

Reject a root level equal to m_rtrefc_maxlevels, matching the ">=" form
already used by the sibling data-device refcount/rmap verifiers and the
in-memory rtrmap verifier.

  BUG: KASAN: slab-out-of-bounds in xfs_btree_lookup (fs/xfs/libxfs/xfs_btree.c:2101)
  Write of size 2 at addr ffff888018391658 by task exploit/144
   xfs_btree_lookup (fs/xfs/libxfs/xfs_btree.c:2101)
   xfs_btree_query_range (fs/xfs/libxfs/xfs_btree.c:5308)
   xfs_refcount_recover_cow_leftovers (fs/xfs/libxfs/xfs_refcount.c:2113)
   xfs_reflink_recover_cow (fs/xfs/xfs_reflink.c:1085)
   xlog_recover_finish (fs/xfs/xfs_log_recover.c:3551)
   xfs_mountfs (fs/xfs/xfs_mount.c:1158)
   xfs_fs_fill_super (fs/xfs/xfs_super.c:1940)
   get_tree_bdev_flags (fs/super.c:1634)
   vfs_get_tree (fs/super.c:1694)
   path_mount (fs/namespace.c:4161)
   __x64_sys_mount (fs/namespace.c:4367)
   entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
  The buggy address belongs to the cache xfs_rtrefcountbt_cur of size 216
  The buggy address is located 8 bytes to the right of
   allocated 216-byte region [ffff888018391578, ffff888018391650)
  Kernel panic - not syncing: Fatal exception

Cc: stable@vger.kernel.org # v6.14
Fixes: 9abe03a0e4 ("xfs: introduce realtime refcount btree ondisk definitions")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:06:24 +02:00
Qiang Ma
87b2a82e13 xfs: clear zapped attr fork state when bmap repair finds no attr fork
xfstests xfs/377 can make xfs_scrub repeatedly check and repair the
attr block map after inode repair zaps an attr fork.

When inode repair zaps an attr fork, it records
XFS_SICK_INO_BMBTA_ZAPPED so that scrub/repair can revisit the attr fork
block map.  If the fork has been reset to an empty state and removed,
BMBTA repair has no attr fork mappings to rebuild and can return success.

The post-repair scrub then runs with XREP_ALREADY_FIXED set, which means
xchk_file_looks_zapped() deliberately ignores the stale zapped health bit
and asks xchk_bmap() to check the current attr fork.  For an absent attr
fork, xchk_bmap() returns -ENOENT.  Returning that error prevents
xchk_bmap_attr() from marking XFS_SICK_INO_BMBTA_ZAPPED healthy, leaving
the zapped health state behind even though there are no attr fork mappings
left to check.

Treat -ENOENT during post-repair BMBTA revalidation as a clean result for
the zapped attr fork: clear XFS_SICK_INO_BMBTA_ZAPPED and return success.
Keep the existing -ENOENT behavior for ordinary scrubs of absent attr
forks.

Fixes: d9041681dd ("xfs: set inode sick state flags when we zap either ondisk fork")
Cc: stable@vger.kernel.org # v6.8
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Qiang Ma <maqianga@uniontech.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-22 15:06:24 +02:00
Guanghui Yang
b7e53968cb xfs: propagate errors from xfs_rtginode_load
xfs_rtginode_ensure() treats every xfs_rtginode_load() error other than
-ENOENT as success.  This can leave the realtime group inode unset after an
I/O, allocation, or corruption error.  Growfs then continues as though the
inode had been loaded.

Only -ENOENT means that the inode needs to be created.  Return all other
errors to the growfs caller.

Fixes: ae897e0bed ("xfs: support creating per-RTG files in growfs")
Cc: stable@vger.kernel.org
Signed-off-by: Guanghui Yang <3497809730@qq.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-20 11:17:32 +02:00
Darrick J. Wong
59c462b0f5 xfs: don't zap bmbt forks if they are MAXLEVELS tall
LOLLM noticed a discrepancy between the bmbt level checks in the libxfs
bmbt code vs. the inode repair code.  We do actually allow a bmbt root
that proclaims to have a height of XFS_BM_MAXLEVELS.

Cc: stable@vger.kernel.org # v6.8
Fixes: e744cef206 ("xfs: zap broken inode forks")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
15e38a9366 xfs: clamp timestamp nanoseconds correctly
LOLLM noticed an off-by-one error in the nsec clamping; fix that so that
we never have tv_nsec == 1e9.

Cc: stable@vger.kernel.org # v6.8
Fixes: 2d295fe657 ("xfs: repair inode records")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
ba150ce634 xfs: fully check the parent handle when it points to the rootdir
LOLLM noticed that the directory tree path checking declares the path to
be ok if the inumber in the parent pointer reaches the root directory.
Unfortunately, it neglects to check that the generation is correct.  Fix
that by moving the generation check up.

Cc: stable@vger.kernel.org # v6.10
Fixes: 928b721a11 ("xfs: teach online scrub to find directory tree structure problems")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
353a5900bc xfs: handle non-inode owners for rtrmap record checking
LOLLM noticed that two helper functions in the rtrmapbt scrub code don't
actually handle non-inode owners correctly -- CoW staging extents and
rgsuperblock extents are not shareable, but they are mergeable.  Fix
these two helpers.

Cc: stable@vger.kernel.org # v6.14
Fixes: 2d9a3e9805 ("xfs: allow overlapping rtrmapbt records for shared data extents")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
5d72a68f20 xfs: fix off-by-one error when calling xchk_xref_has_rt_owner
LOLLM noticed an off-by-one error when computing the length of the
rtrmap to cross-check.

Cc: stable@vger.kernel.org # v6.14
Fixes: 037a44d827 ("xfs: cross-reference the realtime rmapbt")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
540ddc6262 xfs: set xfarray killable sort correctly
LOLLM noticed that we *disable* interruptible sorts when the KILLABLE
flag is set.  This is backwards.  Fix the incorrect logic, and rename
the variable to make the connection more obvious.

Cc: stable@vger.kernel.org # v6.10
Fixes: 271557de7c ("xfs: reduce the rate of cond_resched calls inside scrub")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
ea6e2d9de2 xfs: grab rtrmap btree when checking rgsuper
LOLLM noticed that we aren't grabbing the rtrmap btree when we check the
realtime group superblock.  As a result, none of the cross-referencing
checks have ever run.  Fix this.

Cc: stable@vger.kernel.org # v6.14
Fixes: 428e488465 ("xfs: allow queued realtime intents to drain before scrubbing")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
9af789fa27 xfs: write the rg superblock when fixing it
The rtgroup superblock fixer should write the rtgroup superblock.
LOLLM noticed this, oops. :/

Cc: stable@vger.kernel.org # v6.13
Fixes: 1433f8f9ce ("xfs: repair realtime group superblock")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
881f2eb0fc xfs: use the rt version of the cow staging checker
LOLLM also noticed that xchk_rtrmapbt_xref ought to be using the rtdev
version of the "is this a cow extent?" helper function, not the datadev
one.

Cc: stable@vger.kernel.org # v6.14
Fixes: 91683bb3f2 ("xfs: cross-reference checks with the rt refcount btree")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
ee248157da xfs: use rtrefcount btree cursor in xchk_xref_is_rt_cow_staging
LOLLM points out that we pass the wrong btree cursor here.  We want the
rtrefcount btree cursor, not the non-rt one.  This is fairly benign
since it only affects tracing data.

Cc: stable@vger.kernel.org # v6.14
Fixes: 91683bb3f2 ("xfs: cross-reference checks with the rt refcount btree")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
d766e4e5e8 xfs: don't wrap around quota ids in dqiterate
LOLLM noticed that q_id is an unsigned 32-bit variable.  If it happens
to be set to XFS_DQ_ID_MAX due to a filesystem that actually has a dquot
for ID_MAX, then this addition will truncate to zero and the iteration
starts over.  Fix this by casting to u64.

Cc: stable@vger.kernel.org # v6.8
Fixes: 21d7500929 ("xfs: improve dquot iteration for scrub")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
60a1dde9d2 xfs: move cow_replace_mapping to xfs_bmap_util.c
Move the actual details of (partially) replacing a COW fork mapping to
xfs_bmap_util.c so that all the code doing hairy operations on subsets
of bmbt_irecs are kept together.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
bcb0621204 xfs: make cow repair somewhat flaky when debugging knob enabled
Introduce a new behavior for the cow fork repair code: if the debugging
knob is enabled, we'll pick a random subrange of each cow fork mapping
to mark as bad.  This will exercise the xrep_cow_replace_mapping more
thoroughly.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
a1caeeadbf xfs: don't replace the wrong part of the cow fork
LOLLM points out that xfs_iext_lookup_extent can return a @got where
got->br_startoff < startoff.  In this case, xrep_cow_replace_range
replaces the entire mapping instead of just the part that had been
marked bad in the bitmap, but advances the bitmap cursor in
xrep_cow_replace by the amount replaced.  As a result, we fail to
replace the end of the bad range, and replace part of the good range.

Fix this by rewriting the replace method to handle replacing the middle
of a cow fork mapping.  This we do by returning both the current mapping
as @got, and the subset of the mapping that we want to replace as @rep,
using @rep to store the results of the new allocation, and comparing
@rep to @got to figure out the exact transformations needed.

Cc: stable@vger.kernel.org # v6.8
Fixes: dbbdbd0086 ("xfs: repair problems in CoW forks")
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>
2026-07-14 11:01:47 +02:00
Darrick J. Wong
2f4acd0fcd xfs: resample the data fork mapping after cycling ILOCK
xfs_reflink_fill_{cow_hole,delalloc} are both presented with an inode,
a data fork mapping, and a cow fork mapping.  Unfortunately, these two
helpers cycle the ILOCK to grab a transaction, which means that the
mappings are stale as soon as we reacquire the ILOCK.  Currently we
refresh the cow fork mapping by re-calling xfs_find_trim_cow_extent, but
we don't refresh the data fork mapping beforehand, which means that the
xfs_bmap_trim_cow in that function queries the refcount btree about the
wrong physical blocks and returns an inaccurate value in *shared.

If *shared is now false, the directio write proceeds with a stale data
fork mapping.  Fix this by querying the data fork mapping if the
sequence counter changes across the ILOCK cycle.

Cc: hch@lst.de
Cc: stable@vger.kernel.org # v4.11
Fixes: 3c68d44a2b ("xfs: allocate direct I/O COW blocks in iomap_begin")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-14 11:00:14 +02:00
Andrey Albershteyn
9202ee546b xfs: fix null pointer dereference in tracepoint
If dfp is not NULL we exit early here, when dfp is NULL it's allocated
in xfs_defer_alloc() but not assigned. The tracepoint tries to
dereference members of dfp struct.

Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Cc: stable@vger.kernel.org # v6.8
Fixes: 3f3cec0310 ("xfs: force small EFIs for reaping btree extents")
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2026-07-12 17:32:27 +02:00