* [PATCHSET 3/3] xfs: syzbot fixes for online fsck
@ 2026-01-23 7:00 Darrick J. Wong
2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Darrick J. Wong @ 2026-01-23 7:00 UTC (permalink / raw)
To: djwong, cem; +Cc: hch, stable, r772577952, linux-xfs, r772577952, hch
Hi all,
Fix various syzbot complaints about scrub that Jiaming Zhang found.
If you're going to start using this code, I strongly recommend pulling
from my git trees, which are linked below.
With a bit of luck, this should all go splendidly.
Comments and questions are, as always, welcome.
Unreviewed patches:
[PATCHSET 3/3] xfs: syzbot fixes for online fsck
[PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls
[PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid
[PATCH 5/5] xfs: check for deleted cursors when revalidating two
--D
kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=scrub-syzbot-fixes
---
Commits in this patchset:
* xfs: get rid of the xchk_xfile_*_descr calls
* xfs: only call xf{array,blob}_destroy if we have a valid pointer
* xfs: check return value of xchk_scrub_create_subord
* xfs: fix UAF in xchk_btree_check_block_owner
* xfs: check for deleted cursors when revalidating two btrees
---
fs/xfs/scrub/common.h | 25 -------------------------
fs/xfs/scrub/agheader_repair.c | 21 ++++++++++-----------
fs/xfs/scrub/alloc_repair.c | 20 ++++++++++++++++----
fs/xfs/scrub/attr_repair.c | 26 +++++++++-----------------
fs/xfs/scrub/bmap_repair.c | 6 +-----
fs/xfs/scrub/btree.c | 7 +++++--
fs/xfs/scrub/common.c | 3 +++
fs/xfs/scrub/dir.c | 13 ++++---------
fs/xfs/scrub/dir_repair.c | 19 +++++++++----------
fs/xfs/scrub/dirtree.c | 19 +++++++++----------
fs/xfs/scrub/ialloc_repair.c | 25 ++++++++++++++++++-------
fs/xfs/scrub/nlinks.c | 9 ++++-----
fs/xfs/scrub/parent.c | 11 +++--------
fs/xfs/scrub/parent_repair.c | 23 ++++++-----------------
fs/xfs/scrub/quotacheck.c | 13 +++----------
fs/xfs/scrub/refcount_repair.c | 13 ++-----------
fs/xfs/scrub/repair.c | 3 +++
fs/xfs/scrub/rmap_repair.c | 5 +----
fs/xfs/scrub/rtbitmap_repair.c | 6 ++----
fs/xfs/scrub/rtrefcount_repair.c | 15 +++------------
fs/xfs/scrub/rtrmap_repair.c | 5 +----
fs/xfs/scrub/rtsummary.c | 7 ++-----
fs/xfs/scrub/scrub.c | 2 +-
23 files changed, 115 insertions(+), 181 deletions(-)
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls 2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong @ 2026-01-23 7:03 ` Darrick J. Wong 2026-01-23 14:13 ` Christoph Hellwig 2026-01-23 18:22 ` Jiaming Zhang 2026-01-23 7:03 ` [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer Darrick J. Wong ` (3 subsequent siblings) 4 siblings, 2 replies; 16+ messages in thread From: Darrick J. Wong @ 2026-01-23 7:03 UTC (permalink / raw) To: djwong, cem; +Cc: r772577952, stable, linux-xfs, r772577952, hch From: Darrick J. Wong <djwong@kernel.org> The xchk_xfile_*_descr macros call kasprintf, which can fail to allocate memory if the formatted string is larger than 16 bytes (or whatever the nofail guarantees are nowadays). Some of them could easily exceed that, and Jiaming Zhang found a few places where that can happen with syzbot. The descriptions are debugging aids and aren't required to be unique, so let's just pass in static strings and eliminate this path to failure. Note this patch touches a number of commits, most of which were merged between 6.6 and 6.14. Cc: r772577952@gmail.com Cc: <stable@vger.kernel.org> # v6.12 Fixes: ab97f4b1c03075 ("xfs: repair AGI unlinked inode bucket lists") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> --- fs/xfs/scrub/common.h | 25 ------------------------- fs/xfs/scrub/agheader_repair.c | 13 ++++--------- fs/xfs/scrub/alloc_repair.c | 5 +---- fs/xfs/scrub/attr_repair.c | 20 +++++--------------- fs/xfs/scrub/bmap_repair.c | 6 +----- fs/xfs/scrub/dir.c | 13 ++++--------- fs/xfs/scrub/dir_repair.c | 11 +++-------- fs/xfs/scrub/dirtree.c | 11 +++-------- fs/xfs/scrub/ialloc_repair.c | 5 +---- fs/xfs/scrub/nlinks.c | 6 ++---- fs/xfs/scrub/parent.c | 11 +++-------- fs/xfs/scrub/parent_repair.c | 23 ++++++----------------- fs/xfs/scrub/quotacheck.c | 13 +++---------- fs/xfs/scrub/refcount_repair.c | 13 ++----------- fs/xfs/scrub/rmap_repair.c | 5 +---- fs/xfs/scrub/rtbitmap_repair.c | 6 ++---- fs/xfs/scrub/rtrefcount_repair.c | 15 +++------------ fs/xfs/scrub/rtrmap_repair.c | 5 +---- fs/xfs/scrub/rtsummary.c | 7 ++----- 19 files changed, 47 insertions(+), 166 deletions(-) diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index ddbc065c798cd1..f2ecc68538f0c3 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -246,31 +246,6 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc) int xchk_metadata_inode_forks(struct xfs_scrub *sc); -/* - * Helper macros to allocate and format xfile description strings. - * Callers must kfree the pointer returned. - */ -#define xchk_xfile_descr(sc, fmt, ...) \ - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): " fmt, \ - (sc)->mp->m_super->s_id, ##__VA_ARGS__) -#define xchk_xfile_ag_descr(sc, fmt, ...) \ - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): AG 0x%x " fmt, \ - (sc)->mp->m_super->s_id, \ - (sc)->sa.pag ? \ - pag_agno((sc)->sa.pag) : (sc)->sm->sm_agno, \ - ##__VA_ARGS__) -#define xchk_xfile_ino_descr(sc, fmt, ...) \ - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): inode 0x%llx " fmt, \ - (sc)->mp->m_super->s_id, \ - (sc)->ip ? (sc)->ip->i_ino : (sc)->sm->sm_ino, \ - ##__VA_ARGS__) -#define xchk_xfile_rtgroup_descr(sc, fmt, ...) \ - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): rtgroup 0x%x " fmt, \ - (sc)->mp->m_super->s_id, \ - (sc)->sa.pag ? \ - rtg_rgno((sc)->sr.rtg) : (sc)->sm->sm_agno, \ - ##__VA_ARGS__) - /* * Setting up a hook to wait for intents to drain is costly -- we have to take * the CPU hotplug lock and force an i-cache flush on all CPUs once to set it diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index cd6f0223879f49..a2f6a7f71d8396 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -1708,7 +1708,6 @@ xrep_agi( { struct xrep_agi *ragi; struct xfs_mount *mp = sc->mp; - char *descr; unsigned int i; int error; @@ -1742,17 +1741,13 @@ xrep_agi( xagino_bitmap_init(&ragi->iunlink_bmp); sc->buf_cleanup = xrep_agi_buf_cleanup; - descr = xchk_xfile_ag_descr(sc, "iunlinked next pointers"); - error = xfarray_create(descr, 0, sizeof(xfs_agino_t), - &ragi->iunlink_next); - kfree(descr); + error = xfarray_create("iunlinked next pointers", 0, + sizeof(xfs_agino_t), &ragi->iunlink_next); if (error) return error; - descr = xchk_xfile_ag_descr(sc, "iunlinked prev pointers"); - error = xfarray_create(descr, 0, sizeof(xfs_agino_t), - &ragi->iunlink_prev); - kfree(descr); + error = xfarray_create("iunlinked prev pointers", 0, + sizeof(xfs_agino_t), &ragi->iunlink_prev); if (error) return error; diff --git a/fs/xfs/scrub/alloc_repair.c b/fs/xfs/scrub/alloc_repair.c index bed6a09aa79112..b6fe1f23819eb2 100644 --- a/fs/xfs/scrub/alloc_repair.c +++ b/fs/xfs/scrub/alloc_repair.c @@ -850,7 +850,6 @@ xrep_allocbt( struct xrep_abt *ra; struct xfs_mount *mp = sc->mp; unsigned int busy_gen; - char *descr; int error; /* We require the rmapbt to rebuild anything. */ @@ -876,11 +875,9 @@ xrep_allocbt( } /* Set up enough storage to handle maximally fragmented free space. */ - descr = xchk_xfile_ag_descr(sc, "free space records"); - error = xfarray_create(descr, mp->m_sb.sb_agblocks / 2, + error = xfarray_create("free space records", mp->m_sb.sb_agblocks / 2, sizeof(struct xfs_alloc_rec_incore), &ra->free_records); - kfree(descr); if (error) goto out_ra; diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c index 09d63aa10314b0..eded354dec11ee 100644 --- a/fs/xfs/scrub/attr_repair.c +++ b/fs/xfs/scrub/attr_repair.c @@ -1529,7 +1529,6 @@ xrep_xattr_setup_scan( struct xrep_xattr **rxp) { struct xrep_xattr *rx; - char *descr; int max_len; int error; @@ -1555,35 +1554,26 @@ xrep_xattr_setup_scan( goto out_rx; /* Set up some staging for salvaged attribute keys and values */ - descr = xchk_xfile_ino_descr(sc, "xattr keys"); - error = xfarray_create(descr, 0, sizeof(struct xrep_xattr_key), + error = xfarray_create("xattr keys", 0, sizeof(struct xrep_xattr_key), &rx->xattr_records); - kfree(descr); if (error) goto out_rx; - descr = xchk_xfile_ino_descr(sc, "xattr names"); - error = xfblob_create(descr, &rx->xattr_blobs); - kfree(descr); + error = xfblob_create("xattr names", &rx->xattr_blobs); if (error) goto out_keys; if (xfs_has_parent(sc->mp)) { ASSERT(sc->flags & XCHK_FSGATES_DIRENTS); - descr = xchk_xfile_ino_descr(sc, - "xattr retained parent pointer entries"); - error = xfarray_create(descr, 0, + error = xfarray_create("xattr parent pointer entries", 0, sizeof(struct xrep_xattr_pptr), &rx->pptr_recs); - kfree(descr); if (error) goto out_values; - descr = xchk_xfile_ino_descr(sc, - "xattr retained parent pointer names"); - error = xfblob_create(descr, &rx->pptr_names); - kfree(descr); + error = xfblob_create("xattr parent pointer names", + &rx->pptr_names); if (error) goto out_pprecs; diff --git a/fs/xfs/scrub/bmap_repair.c b/fs/xfs/scrub/bmap_repair.c index 1084213b8e9b88..747cd9389b491d 100644 --- a/fs/xfs/scrub/bmap_repair.c +++ b/fs/xfs/scrub/bmap_repair.c @@ -923,7 +923,6 @@ xrep_bmap( bool allow_unwritten) { struct xrep_bmap *rb; - char *descr; xfs_extnum_t max_bmbt_recs; bool large_extcount; int error = 0; @@ -945,11 +944,8 @@ xrep_bmap( /* Set up enough storage to handle the max records for this fork. */ large_extcount = xfs_has_large_extent_counts(sc->mp); max_bmbt_recs = xfs_iext_max_nextents(large_extcount, whichfork); - descr = xchk_xfile_ino_descr(sc, "%s fork mapping records", - whichfork == XFS_DATA_FORK ? "data" : "attr"); - error = xfarray_create(descr, max_bmbt_recs, + error = xfarray_create("fork mapping records", max_bmbt_recs, sizeof(struct xfs_bmbt_rec), &rb->bmap_records); - kfree(descr); if (error) goto out_rb; diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c index c877bde71e6280..4f849d98cbdd22 100644 --- a/fs/xfs/scrub/dir.c +++ b/fs/xfs/scrub/dir.c @@ -1102,22 +1102,17 @@ xchk_directory( sd->xname.name = sd->namebuf; if (xfs_has_parent(sc->mp)) { - char *descr; - /* * Set up some staging memory for dirents that we can't check * due to locking contention. */ - descr = xchk_xfile_ino_descr(sc, "slow directory entries"); - error = xfarray_create(descr, 0, sizeof(struct xchk_dirent), - &sd->dir_entries); - kfree(descr); + error = xfarray_create("slow directory entries", 0, + sizeof(struct xchk_dirent), &sd->dir_entries); if (error) goto out_sd; - descr = xchk_xfile_ino_descr(sc, "slow directory entry names"); - error = xfblob_create(descr, &sd->dir_names); - kfree(descr); + error = xfblob_create("slow directory entry names", + &sd->dir_names); if (error) goto out_entries; } diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index 8d3b550990b58a..7a21b688a47158 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -1784,20 +1784,15 @@ xrep_dir_setup_scan( struct xrep_dir *rd) { struct xfs_scrub *sc = rd->sc; - char *descr; int error; /* Set up some staging memory for salvaging dirents. */ - descr = xchk_xfile_ino_descr(sc, "directory entries"); - error = xfarray_create(descr, 0, sizeof(struct xrep_dirent), - &rd->dir_entries); - kfree(descr); + error = xfarray_create("directory entries", 0, + sizeof(struct xrep_dirent), &rd->dir_entries); if (error) return error; - descr = xchk_xfile_ino_descr(sc, "directory entry names"); - error = xfblob_create(descr, &rd->dir_names); - kfree(descr); + error = xfblob_create("directory entry names", &rd->dir_names); if (error) goto out_xfarray; diff --git a/fs/xfs/scrub/dirtree.c b/fs/xfs/scrub/dirtree.c index 3a9cdf8738b6db..f9c85b8b194fa4 100644 --- a/fs/xfs/scrub/dirtree.c +++ b/fs/xfs/scrub/dirtree.c @@ -92,7 +92,6 @@ xchk_setup_dirtree( struct xfs_scrub *sc) { struct xchk_dirtree *dl; - char *descr; int error; xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS); @@ -116,16 +115,12 @@ xchk_setup_dirtree( mutex_init(&dl->lock); - descr = xchk_xfile_ino_descr(sc, "dirtree path steps"); - error = xfarray_create(descr, 0, sizeof(struct xchk_dirpath_step), - &dl->path_steps); - kfree(descr); + error = xfarray_create("dirtree path steps", 0, + sizeof(struct xchk_dirpath_step), &dl->path_steps); if (error) goto out_dl; - descr = xchk_xfile_ino_descr(sc, "dirtree path names"); - error = xfblob_create(descr, &dl->path_names); - kfree(descr); + error = xfblob_create("dirtree path names", &dl->path_names); if (error) goto out_steps; diff --git a/fs/xfs/scrub/ialloc_repair.c b/fs/xfs/scrub/ialloc_repair.c index 14e48d3f1912bf..b1d00167d263f4 100644 --- a/fs/xfs/scrub/ialloc_repair.c +++ b/fs/xfs/scrub/ialloc_repair.c @@ -797,7 +797,6 @@ xrep_iallocbt( { struct xrep_ibt *ri; struct xfs_mount *mp = sc->mp; - char *descr; xfs_agino_t first_agino, last_agino; int error = 0; @@ -816,11 +815,9 @@ xrep_iallocbt( /* Set up enough storage to handle an AG with nothing but inodes. */ xfs_agino_range(mp, pag_agno(sc->sa.pag), &first_agino, &last_agino); last_agino /= XFS_INODES_PER_CHUNK; - descr = xchk_xfile_ag_descr(sc, "inode index records"); - error = xfarray_create(descr, last_agino, + error = xfarray_create("inode index records", last_agino, sizeof(struct xfs_inobt_rec_incore), &ri->inode_records); - kfree(descr); if (error) goto out_ri; diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c index 091c79e432e592..2ba686e4de8bc5 100644 --- a/fs/xfs/scrub/nlinks.c +++ b/fs/xfs/scrub/nlinks.c @@ -990,7 +990,6 @@ xchk_nlinks_setup_scan( struct xchk_nlink_ctrs *xnc) { struct xfs_mount *mp = sc->mp; - char *descr; unsigned long long max_inos; xfs_agnumber_t last_agno = mp->m_sb.sb_agcount - 1; xfs_agino_t first_agino, last_agino; @@ -1007,10 +1006,9 @@ xchk_nlinks_setup_scan( */ xfs_agino_range(mp, last_agno, &first_agino, &last_agino); max_inos = XFS_AGINO_TO_INO(mp, last_agno, last_agino) + 1; - descr = xchk_xfile_descr(sc, "file link counts"); - error = xfarray_create(descr, min(XFS_MAXINUMBER + 1, max_inos), + error = xfarray_create("file link counts", + min(XFS_MAXINUMBER + 1, max_inos), sizeof(struct xchk_nlink), &xnc->nlinks); - kfree(descr); if (error) goto out_teardown; diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c index 11d5de10fd567b..23c195d14494e5 100644 --- a/fs/xfs/scrub/parent.c +++ b/fs/xfs/scrub/parent.c @@ -755,7 +755,6 @@ xchk_parent_pptr( struct xfs_scrub *sc) { struct xchk_pptrs *pp; - char *descr; int error; pp = kvzalloc(sizeof(struct xchk_pptrs), XCHK_GFP_FLAGS); @@ -768,16 +767,12 @@ xchk_parent_pptr( * Set up some staging memory for parent pointers that we can't check * due to locking contention. */ - descr = xchk_xfile_ino_descr(sc, "slow parent pointer entries"); - error = xfarray_create(descr, 0, sizeof(struct xchk_pptr), - &pp->pptr_entries); - kfree(descr); + error = xfarray_create("slow parent pointer entries", 0, + sizeof(struct xchk_pptr), &pp->pptr_entries); if (error) goto out_pp; - descr = xchk_xfile_ino_descr(sc, "slow parent pointer names"); - error = xfblob_create(descr, &pp->pptr_names); - kfree(descr); + error = xfblob_create("slow parent pointer names", &pp->pptr_names); if (error) goto out_entries; diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c index 2949feda627175..897902c54178d4 100644 --- a/fs/xfs/scrub/parent_repair.c +++ b/fs/xfs/scrub/parent_repair.c @@ -1497,7 +1497,6 @@ xrep_parent_setup_scan( struct xrep_parent *rp) { struct xfs_scrub *sc = rp->sc; - char *descr; struct xfs_da_geometry *geo = sc->mp->m_attr_geo; int max_len; int error; @@ -1525,32 +1524,22 @@ xrep_parent_setup_scan( goto out_xattr_name; /* Set up some staging memory for logging parent pointer updates. */ - descr = xchk_xfile_ino_descr(sc, "parent pointer entries"); - error = xfarray_create(descr, 0, sizeof(struct xrep_pptr), - &rp->pptr_recs); - kfree(descr); + error = xfarray_create("parent pointer entries", 0, + sizeof(struct xrep_pptr), &rp->pptr_recs); if (error) goto out_xattr_value; - descr = xchk_xfile_ino_descr(sc, "parent pointer names"); - error = xfblob_create(descr, &rp->pptr_names); - kfree(descr); + error = xfblob_create("parent pointer names", &rp->pptr_names); if (error) goto out_recs; /* Set up some storage for copying attrs before the mapping exchange */ - descr = xchk_xfile_ino_descr(sc, - "parent pointer retained xattr entries"); - error = xfarray_create(descr, 0, sizeof(struct xrep_parent_xattr), - &rp->xattr_records); - kfree(descr); + error = xfarray_create("parent pointer xattr entries", 0, + sizeof(struct xrep_parent_xattr), &rp->xattr_records); if (error) goto out_names; - descr = xchk_xfile_ino_descr(sc, - "parent pointer retained xattr values"); - error = xfblob_create(descr, &rp->xattr_blobs); - kfree(descr); + error = xfblob_create("parent pointer xattr values", &rp->xattr_blobs); if (error) goto out_attr_keys; diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c index d412a8359784ee..3b2f4ccde2ec09 100644 --- a/fs/xfs/scrub/quotacheck.c +++ b/fs/xfs/scrub/quotacheck.c @@ -741,7 +741,6 @@ xqcheck_setup_scan( struct xfs_scrub *sc, struct xqcheck *xqc) { - char *descr; struct xfs_quotainfo *qi = sc->mp->m_quotainfo; unsigned long long max_dquots = XFS_DQ_ID_MAX + 1ULL; int error; @@ -756,28 +755,22 @@ xqcheck_setup_scan( error = -ENOMEM; if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) { - descr = xchk_xfile_descr(sc, "user dquot records"); - error = xfarray_create(descr, max_dquots, + error = xfarray_create("user dquot records", max_dquots, sizeof(struct xqcheck_dquot), &xqc->ucounts); - kfree(descr); if (error) goto out_teardown; } if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) { - descr = xchk_xfile_descr(sc, "group dquot records"); - error = xfarray_create(descr, max_dquots, + error = xfarray_create("group dquot records", max_dquots, sizeof(struct xqcheck_dquot), &xqc->gcounts); - kfree(descr); if (error) goto out_teardown; } if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) { - descr = xchk_xfile_descr(sc, "project dquot records"); - error = xfarray_create(descr, max_dquots, + error = xfarray_create("project dquot records", max_dquots, sizeof(struct xqcheck_dquot), &xqc->pcounts); - kfree(descr); if (error) goto out_teardown; } diff --git a/fs/xfs/scrub/refcount_repair.c b/fs/xfs/scrub/refcount_repair.c index 9c8cb5332da042..360fd7354880a7 100644 --- a/fs/xfs/scrub/refcount_repair.c +++ b/fs/xfs/scrub/refcount_repair.c @@ -123,13 +123,7 @@ int xrep_setup_ag_refcountbt( struct xfs_scrub *sc) { - char *descr; - int error; - - descr = xchk_xfile_ag_descr(sc, "rmap record bag"); - error = xrep_setup_xfbtree(sc, descr); - kfree(descr); - return error; + return xrep_setup_xfbtree(sc, "rmap record bag"); } /* Check for any obvious conflicts with this shared/CoW staging extent. */ @@ -704,7 +698,6 @@ xrep_refcountbt( { struct xrep_refc *rr; struct xfs_mount *mp = sc->mp; - char *descr; int error; /* We require the rmapbt to rebuild anything. */ @@ -717,11 +710,9 @@ xrep_refcountbt( rr->sc = sc; /* Set up enough storage to handle one refcount record per block. */ - descr = xchk_xfile_ag_descr(sc, "reference count records"); - error = xfarray_create(descr, mp->m_sb.sb_agblocks, + error = xfarray_create("reference count records", mp->m_sb.sb_agblocks, sizeof(struct xfs_refcount_irec), &rr->refcount_records); - kfree(descr); if (error) goto out_rr; diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c index 17d4a38d735cb8..cfd1cf403b37eb 100644 --- a/fs/xfs/scrub/rmap_repair.c +++ b/fs/xfs/scrub/rmap_repair.c @@ -164,14 +164,11 @@ xrep_setup_ag_rmapbt( struct xfs_scrub *sc) { struct xrep_rmap *rr; - char *descr; int error; xchk_fsgates_enable(sc, XCHK_FSGATES_RMAP); - descr = xchk_xfile_ag_descr(sc, "reverse mapping records"); - error = xrep_setup_xfbtree(sc, descr); - kfree(descr); + error = xrep_setup_xfbtree(sc, "reverse mapping records"); if (error) return error; diff --git a/fs/xfs/scrub/rtbitmap_repair.c b/fs/xfs/scrub/rtbitmap_repair.c index 203a1a97c5026e..41d6736a529d02 100644 --- a/fs/xfs/scrub/rtbitmap_repair.c +++ b/fs/xfs/scrub/rtbitmap_repair.c @@ -43,7 +43,6 @@ xrep_setup_rtbitmap( struct xchk_rtbitmap *rtb) { struct xfs_mount *mp = sc->mp; - char *descr; unsigned long long blocks = mp->m_sb.sb_rbmblocks; int error; @@ -52,9 +51,8 @@ xrep_setup_rtbitmap( return error; /* Create an xfile to hold our reconstructed bitmap. */ - descr = xchk_xfile_rtgroup_descr(sc, "bitmap file"); - error = xfile_create(descr, blocks * mp->m_sb.sb_blocksize, &sc->xfile); - kfree(descr); + error = xfile_create("realtime bitmap file", + blocks * mp->m_sb.sb_blocksize, &sc->xfile); if (error) return error; diff --git a/fs/xfs/scrub/rtrefcount_repair.c b/fs/xfs/scrub/rtrefcount_repair.c index 983362447826de..b35e39cce7ad5a 100644 --- a/fs/xfs/scrub/rtrefcount_repair.c +++ b/fs/xfs/scrub/rtrefcount_repair.c @@ -128,13 +128,7 @@ int xrep_setup_rtrefcountbt( struct xfs_scrub *sc) { - char *descr; - int error; - - descr = xchk_xfile_ag_descr(sc, "rmap record bag"); - error = xrep_setup_xfbtree(sc, descr); - kfree(descr); - return error; + return xrep_setup_xfbtree(sc, "realtime rmap record bag"); } /* Check for any obvious conflicts with this shared/CoW staging extent. */ @@ -704,7 +698,6 @@ xrep_rtrefcountbt( { struct xrep_rtrefc *rr; struct xfs_mount *mp = sc->mp; - char *descr; int error; /* We require the rmapbt to rebuild anything. */ @@ -722,11 +715,9 @@ xrep_rtrefcountbt( rr->sc = sc; /* Set up enough storage to handle one refcount record per rt extent. */ - descr = xchk_xfile_ag_descr(sc, "reference count records"); - error = xfarray_create(descr, mp->m_sb.sb_rextents, - sizeof(struct xfs_refcount_irec), + error = xfarray_create("realtime reference count records", + mp->m_sb.sb_rextents, sizeof(struct xfs_refcount_irec), &rr->refcount_records); - kfree(descr); if (error) goto out_rr; diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c index 7561941a337a1f..749977a66e40ff 100644 --- a/fs/xfs/scrub/rtrmap_repair.c +++ b/fs/xfs/scrub/rtrmap_repair.c @@ -103,14 +103,11 @@ xrep_setup_rtrmapbt( struct xfs_scrub *sc) { struct xrep_rtrmap *rr; - char *descr; int error; xchk_fsgates_enable(sc, XCHK_FSGATES_RMAP); - descr = xchk_xfile_rtgroup_descr(sc, "reverse mapping records"); - error = xrep_setup_xfbtree(sc, descr); - kfree(descr); + error = xrep_setup_xfbtree(sc, "realtime reverse mapping records"); if (error) return error; diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c index 4ac679c1bd29cd..fb78cff2ac3a16 100644 --- a/fs/xfs/scrub/rtsummary.c +++ b/fs/xfs/scrub/rtsummary.c @@ -43,7 +43,6 @@ xchk_setup_rtsummary( struct xfs_scrub *sc) { struct xfs_mount *mp = sc->mp; - char *descr; struct xchk_rtsummary *rts; int error; @@ -70,10 +69,8 @@ xchk_setup_rtsummary( * Create an xfile to construct a new rtsummary file. The xfile allows * us to avoid pinning kernel memory for this purpose. */ - descr = xchk_xfile_descr(sc, "realtime summary file"); - error = xfile_create(descr, XFS_FSB_TO_B(mp, mp->m_rsumblocks), - &sc->xfile); - kfree(descr); + error = xfile_create("realtime summary file", + XFS_FSB_TO_B(mp, mp->m_rsumblocks), &sc->xfile); if (error) return error; ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls 2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong @ 2026-01-23 14:13 ` Christoph Hellwig 2026-01-23 18:22 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Christoph Hellwig @ 2026-01-23 14:13 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, r772577952, stable, linux-xfs, hch Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls 2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong 2026-01-23 14:13 ` Christoph Hellwig @ 2026-01-23 18:22 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Jiaming Zhang @ 2026-01-23 18:22 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, stable, linux-xfs, hch Darrick J. Wong <djwong@kernel.org> 于2026年1月23日周五 15:03写道: > > From: Darrick J. Wong <djwong@kernel.org> > > The xchk_xfile_*_descr macros call kasprintf, which can fail to allocate > memory if the formatted string is larger than 16 bytes (or whatever the > nofail guarantees are nowadays). Some of them could easily exceed that, > and Jiaming Zhang found a few places where that can happen with syzbot. > > The descriptions are debugging aids and aren't required to be unique, so > let's just pass in static strings and eliminate this path to failure. > Note this patch touches a number of commits, most of which were merged > between 6.6 and 6.14. > > Cc: r772577952@gmail.com > Cc: <stable@vger.kernel.org> # v6.12 > Fixes: ab97f4b1c03075 ("xfs: repair AGI unlinked inode bucket lists") > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > --- > fs/xfs/scrub/common.h | 25 ------------------------- > fs/xfs/scrub/agheader_repair.c | 13 ++++--------- > fs/xfs/scrub/alloc_repair.c | 5 +---- > fs/xfs/scrub/attr_repair.c | 20 +++++--------------- > fs/xfs/scrub/bmap_repair.c | 6 +----- > fs/xfs/scrub/dir.c | 13 ++++--------- > fs/xfs/scrub/dir_repair.c | 11 +++-------- > fs/xfs/scrub/dirtree.c | 11 +++-------- > fs/xfs/scrub/ialloc_repair.c | 5 +---- > fs/xfs/scrub/nlinks.c | 6 ++---- > fs/xfs/scrub/parent.c | 11 +++-------- > fs/xfs/scrub/parent_repair.c | 23 ++++++----------------- > fs/xfs/scrub/quotacheck.c | 13 +++---------- > fs/xfs/scrub/refcount_repair.c | 13 ++----------- > fs/xfs/scrub/rmap_repair.c | 5 +---- > fs/xfs/scrub/rtbitmap_repair.c | 6 ++---- > fs/xfs/scrub/rtrefcount_repair.c | 15 +++------------ > fs/xfs/scrub/rtrmap_repair.c | 5 +---- > fs/xfs/scrub/rtsummary.c | 7 ++----- > 19 files changed, 47 insertions(+), 166 deletions(-) > > > diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h > index ddbc065c798cd1..f2ecc68538f0c3 100644 > --- a/fs/xfs/scrub/common.h > +++ b/fs/xfs/scrub/common.h > @@ -246,31 +246,6 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc) > > int xchk_metadata_inode_forks(struct xfs_scrub *sc); > > -/* > - * Helper macros to allocate and format xfile description strings. > - * Callers must kfree the pointer returned. > - */ > -#define xchk_xfile_descr(sc, fmt, ...) \ > - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): " fmt, \ > - (sc)->mp->m_super->s_id, ##__VA_ARGS__) > -#define xchk_xfile_ag_descr(sc, fmt, ...) \ > - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): AG 0x%x " fmt, \ > - (sc)->mp->m_super->s_id, \ > - (sc)->sa.pag ? \ > - pag_agno((sc)->sa.pag) : (sc)->sm->sm_agno, \ > - ##__VA_ARGS__) > -#define xchk_xfile_ino_descr(sc, fmt, ...) \ > - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): inode 0x%llx " fmt, \ > - (sc)->mp->m_super->s_id, \ > - (sc)->ip ? (sc)->ip->i_ino : (sc)->sm->sm_ino, \ > - ##__VA_ARGS__) > -#define xchk_xfile_rtgroup_descr(sc, fmt, ...) \ > - kasprintf(XCHK_GFP_FLAGS, "XFS (%s): rtgroup 0x%x " fmt, \ > - (sc)->mp->m_super->s_id, \ > - (sc)->sa.pag ? \ > - rtg_rgno((sc)->sr.rtg) : (sc)->sm->sm_agno, \ > - ##__VA_ARGS__) > - > /* > * Setting up a hook to wait for intents to drain is costly -- we have to take > * the CPU hotplug lock and force an i-cache flush on all CPUs once to set it > diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c > index cd6f0223879f49..a2f6a7f71d8396 100644 > --- a/fs/xfs/scrub/agheader_repair.c > +++ b/fs/xfs/scrub/agheader_repair.c > @@ -1708,7 +1708,6 @@ xrep_agi( > { > struct xrep_agi *ragi; > struct xfs_mount *mp = sc->mp; > - char *descr; > unsigned int i; > int error; > > @@ -1742,17 +1741,13 @@ xrep_agi( > xagino_bitmap_init(&ragi->iunlink_bmp); > sc->buf_cleanup = xrep_agi_buf_cleanup; > > - descr = xchk_xfile_ag_descr(sc, "iunlinked next pointers"); > - error = xfarray_create(descr, 0, sizeof(xfs_agino_t), > - &ragi->iunlink_next); > - kfree(descr); > + error = xfarray_create("iunlinked next pointers", 0, > + sizeof(xfs_agino_t), &ragi->iunlink_next); > if (error) > return error; > > - descr = xchk_xfile_ag_descr(sc, "iunlinked prev pointers"); > - error = xfarray_create(descr, 0, sizeof(xfs_agino_t), > - &ragi->iunlink_prev); > - kfree(descr); > + error = xfarray_create("iunlinked prev pointers", 0, > + sizeof(xfs_agino_t), &ragi->iunlink_prev); > if (error) > return error; > > diff --git a/fs/xfs/scrub/alloc_repair.c b/fs/xfs/scrub/alloc_repair.c > index bed6a09aa79112..b6fe1f23819eb2 100644 > --- a/fs/xfs/scrub/alloc_repair.c > +++ b/fs/xfs/scrub/alloc_repair.c > @@ -850,7 +850,6 @@ xrep_allocbt( > struct xrep_abt *ra; > struct xfs_mount *mp = sc->mp; > unsigned int busy_gen; > - char *descr; > int error; > > /* We require the rmapbt to rebuild anything. */ > @@ -876,11 +875,9 @@ xrep_allocbt( > } > > /* Set up enough storage to handle maximally fragmented free space. */ > - descr = xchk_xfile_ag_descr(sc, "free space records"); > - error = xfarray_create(descr, mp->m_sb.sb_agblocks / 2, > + error = xfarray_create("free space records", mp->m_sb.sb_agblocks / 2, > sizeof(struct xfs_alloc_rec_incore), > &ra->free_records); > - kfree(descr); > if (error) > goto out_ra; > > diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c > index 09d63aa10314b0..eded354dec11ee 100644 > --- a/fs/xfs/scrub/attr_repair.c > +++ b/fs/xfs/scrub/attr_repair.c > @@ -1529,7 +1529,6 @@ xrep_xattr_setup_scan( > struct xrep_xattr **rxp) > { > struct xrep_xattr *rx; > - char *descr; > int max_len; > int error; > > @@ -1555,35 +1554,26 @@ xrep_xattr_setup_scan( > goto out_rx; > > /* Set up some staging for salvaged attribute keys and values */ > - descr = xchk_xfile_ino_descr(sc, "xattr keys"); > - error = xfarray_create(descr, 0, sizeof(struct xrep_xattr_key), > + error = xfarray_create("xattr keys", 0, sizeof(struct xrep_xattr_key), > &rx->xattr_records); > - kfree(descr); > if (error) > goto out_rx; > > - descr = xchk_xfile_ino_descr(sc, "xattr names"); > - error = xfblob_create(descr, &rx->xattr_blobs); > - kfree(descr); > + error = xfblob_create("xattr names", &rx->xattr_blobs); > if (error) > goto out_keys; > > if (xfs_has_parent(sc->mp)) { > ASSERT(sc->flags & XCHK_FSGATES_DIRENTS); > > - descr = xchk_xfile_ino_descr(sc, > - "xattr retained parent pointer entries"); > - error = xfarray_create(descr, 0, > + error = xfarray_create("xattr parent pointer entries", 0, > sizeof(struct xrep_xattr_pptr), > &rx->pptr_recs); > - kfree(descr); > if (error) > goto out_values; > > - descr = xchk_xfile_ino_descr(sc, > - "xattr retained parent pointer names"); > - error = xfblob_create(descr, &rx->pptr_names); > - kfree(descr); > + error = xfblob_create("xattr parent pointer names", > + &rx->pptr_names); > if (error) > goto out_pprecs; > > diff --git a/fs/xfs/scrub/bmap_repair.c b/fs/xfs/scrub/bmap_repair.c > index 1084213b8e9b88..747cd9389b491d 100644 > --- a/fs/xfs/scrub/bmap_repair.c > +++ b/fs/xfs/scrub/bmap_repair.c > @@ -923,7 +923,6 @@ xrep_bmap( > bool allow_unwritten) > { > struct xrep_bmap *rb; > - char *descr; > xfs_extnum_t max_bmbt_recs; > bool large_extcount; > int error = 0; > @@ -945,11 +944,8 @@ xrep_bmap( > /* Set up enough storage to handle the max records for this fork. */ > large_extcount = xfs_has_large_extent_counts(sc->mp); > max_bmbt_recs = xfs_iext_max_nextents(large_extcount, whichfork); > - descr = xchk_xfile_ino_descr(sc, "%s fork mapping records", > - whichfork == XFS_DATA_FORK ? "data" : "attr"); > - error = xfarray_create(descr, max_bmbt_recs, > + error = xfarray_create("fork mapping records", max_bmbt_recs, > sizeof(struct xfs_bmbt_rec), &rb->bmap_records); > - kfree(descr); > if (error) > goto out_rb; > > diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c > index c877bde71e6280..4f849d98cbdd22 100644 > --- a/fs/xfs/scrub/dir.c > +++ b/fs/xfs/scrub/dir.c > @@ -1102,22 +1102,17 @@ xchk_directory( > sd->xname.name = sd->namebuf; > > if (xfs_has_parent(sc->mp)) { > - char *descr; > - > /* > * Set up some staging memory for dirents that we can't check > * due to locking contention. > */ > - descr = xchk_xfile_ino_descr(sc, "slow directory entries"); > - error = xfarray_create(descr, 0, sizeof(struct xchk_dirent), > - &sd->dir_entries); > - kfree(descr); > + error = xfarray_create("slow directory entries", 0, > + sizeof(struct xchk_dirent), &sd->dir_entries); > if (error) > goto out_sd; > > - descr = xchk_xfile_ino_descr(sc, "slow directory entry names"); > - error = xfblob_create(descr, &sd->dir_names); > - kfree(descr); > + error = xfblob_create("slow directory entry names", > + &sd->dir_names); > if (error) > goto out_entries; > } > diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c > index 8d3b550990b58a..7a21b688a47158 100644 > --- a/fs/xfs/scrub/dir_repair.c > +++ b/fs/xfs/scrub/dir_repair.c > @@ -1784,20 +1784,15 @@ xrep_dir_setup_scan( > struct xrep_dir *rd) > { > struct xfs_scrub *sc = rd->sc; > - char *descr; > int error; > > /* Set up some staging memory for salvaging dirents. */ > - descr = xchk_xfile_ino_descr(sc, "directory entries"); > - error = xfarray_create(descr, 0, sizeof(struct xrep_dirent), > - &rd->dir_entries); > - kfree(descr); > + error = xfarray_create("directory entries", 0, > + sizeof(struct xrep_dirent), &rd->dir_entries); > if (error) > return error; > > - descr = xchk_xfile_ino_descr(sc, "directory entry names"); > - error = xfblob_create(descr, &rd->dir_names); > - kfree(descr); > + error = xfblob_create("directory entry names", &rd->dir_names); > if (error) > goto out_xfarray; > > diff --git a/fs/xfs/scrub/dirtree.c b/fs/xfs/scrub/dirtree.c > index 3a9cdf8738b6db..f9c85b8b194fa4 100644 > --- a/fs/xfs/scrub/dirtree.c > +++ b/fs/xfs/scrub/dirtree.c > @@ -92,7 +92,6 @@ xchk_setup_dirtree( > struct xfs_scrub *sc) > { > struct xchk_dirtree *dl; > - char *descr; > int error; > > xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS); > @@ -116,16 +115,12 @@ xchk_setup_dirtree( > > mutex_init(&dl->lock); > > - descr = xchk_xfile_ino_descr(sc, "dirtree path steps"); > - error = xfarray_create(descr, 0, sizeof(struct xchk_dirpath_step), > - &dl->path_steps); > - kfree(descr); > + error = xfarray_create("dirtree path steps", 0, > + sizeof(struct xchk_dirpath_step), &dl->path_steps); > if (error) > goto out_dl; > > - descr = xchk_xfile_ino_descr(sc, "dirtree path names"); > - error = xfblob_create(descr, &dl->path_names); > - kfree(descr); > + error = xfblob_create("dirtree path names", &dl->path_names); > if (error) > goto out_steps; > > diff --git a/fs/xfs/scrub/ialloc_repair.c b/fs/xfs/scrub/ialloc_repair.c > index 14e48d3f1912bf..b1d00167d263f4 100644 > --- a/fs/xfs/scrub/ialloc_repair.c > +++ b/fs/xfs/scrub/ialloc_repair.c > @@ -797,7 +797,6 @@ xrep_iallocbt( > { > struct xrep_ibt *ri; > struct xfs_mount *mp = sc->mp; > - char *descr; > xfs_agino_t first_agino, last_agino; > int error = 0; > > @@ -816,11 +815,9 @@ xrep_iallocbt( > /* Set up enough storage to handle an AG with nothing but inodes. */ > xfs_agino_range(mp, pag_agno(sc->sa.pag), &first_agino, &last_agino); > last_agino /= XFS_INODES_PER_CHUNK; > - descr = xchk_xfile_ag_descr(sc, "inode index records"); > - error = xfarray_create(descr, last_agino, > + error = xfarray_create("inode index records", last_agino, > sizeof(struct xfs_inobt_rec_incore), > &ri->inode_records); > - kfree(descr); > if (error) > goto out_ri; > > diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c > index 091c79e432e592..2ba686e4de8bc5 100644 > --- a/fs/xfs/scrub/nlinks.c > +++ b/fs/xfs/scrub/nlinks.c > @@ -990,7 +990,6 @@ xchk_nlinks_setup_scan( > struct xchk_nlink_ctrs *xnc) > { > struct xfs_mount *mp = sc->mp; > - char *descr; > unsigned long long max_inos; > xfs_agnumber_t last_agno = mp->m_sb.sb_agcount - 1; > xfs_agino_t first_agino, last_agino; > @@ -1007,10 +1006,9 @@ xchk_nlinks_setup_scan( > */ > xfs_agino_range(mp, last_agno, &first_agino, &last_agino); > max_inos = XFS_AGINO_TO_INO(mp, last_agno, last_agino) + 1; > - descr = xchk_xfile_descr(sc, "file link counts"); > - error = xfarray_create(descr, min(XFS_MAXINUMBER + 1, max_inos), > + error = xfarray_create("file link counts", > + min(XFS_MAXINUMBER + 1, max_inos), > sizeof(struct xchk_nlink), &xnc->nlinks); > - kfree(descr); > if (error) > goto out_teardown; > > diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c > index 11d5de10fd567b..23c195d14494e5 100644 > --- a/fs/xfs/scrub/parent.c > +++ b/fs/xfs/scrub/parent.c > @@ -755,7 +755,6 @@ xchk_parent_pptr( > struct xfs_scrub *sc) > { > struct xchk_pptrs *pp; > - char *descr; > int error; > > pp = kvzalloc(sizeof(struct xchk_pptrs), XCHK_GFP_FLAGS); > @@ -768,16 +767,12 @@ xchk_parent_pptr( > * Set up some staging memory for parent pointers that we can't check > * due to locking contention. > */ > - descr = xchk_xfile_ino_descr(sc, "slow parent pointer entries"); > - error = xfarray_create(descr, 0, sizeof(struct xchk_pptr), > - &pp->pptr_entries); > - kfree(descr); > + error = xfarray_create("slow parent pointer entries", 0, > + sizeof(struct xchk_pptr), &pp->pptr_entries); > if (error) > goto out_pp; > > - descr = xchk_xfile_ino_descr(sc, "slow parent pointer names"); > - error = xfblob_create(descr, &pp->pptr_names); > - kfree(descr); > + error = xfblob_create("slow parent pointer names", &pp->pptr_names); > if (error) > goto out_entries; > > diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c > index 2949feda627175..897902c54178d4 100644 > --- a/fs/xfs/scrub/parent_repair.c > +++ b/fs/xfs/scrub/parent_repair.c > @@ -1497,7 +1497,6 @@ xrep_parent_setup_scan( > struct xrep_parent *rp) > { > struct xfs_scrub *sc = rp->sc; > - char *descr; > struct xfs_da_geometry *geo = sc->mp->m_attr_geo; > int max_len; > int error; > @@ -1525,32 +1524,22 @@ xrep_parent_setup_scan( > goto out_xattr_name; > > /* Set up some staging memory for logging parent pointer updates. */ > - descr = xchk_xfile_ino_descr(sc, "parent pointer entries"); > - error = xfarray_create(descr, 0, sizeof(struct xrep_pptr), > - &rp->pptr_recs); > - kfree(descr); > + error = xfarray_create("parent pointer entries", 0, > + sizeof(struct xrep_pptr), &rp->pptr_recs); > if (error) > goto out_xattr_value; > > - descr = xchk_xfile_ino_descr(sc, "parent pointer names"); > - error = xfblob_create(descr, &rp->pptr_names); > - kfree(descr); > + error = xfblob_create("parent pointer names", &rp->pptr_names); > if (error) > goto out_recs; > > /* Set up some storage for copying attrs before the mapping exchange */ > - descr = xchk_xfile_ino_descr(sc, > - "parent pointer retained xattr entries"); > - error = xfarray_create(descr, 0, sizeof(struct xrep_parent_xattr), > - &rp->xattr_records); > - kfree(descr); > + error = xfarray_create("parent pointer xattr entries", 0, > + sizeof(struct xrep_parent_xattr), &rp->xattr_records); > if (error) > goto out_names; > > - descr = xchk_xfile_ino_descr(sc, > - "parent pointer retained xattr values"); > - error = xfblob_create(descr, &rp->xattr_blobs); > - kfree(descr); > + error = xfblob_create("parent pointer xattr values", &rp->xattr_blobs); > if (error) > goto out_attr_keys; > > diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c > index d412a8359784ee..3b2f4ccde2ec09 100644 > --- a/fs/xfs/scrub/quotacheck.c > +++ b/fs/xfs/scrub/quotacheck.c > @@ -741,7 +741,6 @@ xqcheck_setup_scan( > struct xfs_scrub *sc, > struct xqcheck *xqc) > { > - char *descr; > struct xfs_quotainfo *qi = sc->mp->m_quotainfo; > unsigned long long max_dquots = XFS_DQ_ID_MAX + 1ULL; > int error; > @@ -756,28 +755,22 @@ xqcheck_setup_scan( > > error = -ENOMEM; > if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) { > - descr = xchk_xfile_descr(sc, "user dquot records"); > - error = xfarray_create(descr, max_dquots, > + error = xfarray_create("user dquot records", max_dquots, > sizeof(struct xqcheck_dquot), &xqc->ucounts); > - kfree(descr); > if (error) > goto out_teardown; > } > > if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) { > - descr = xchk_xfile_descr(sc, "group dquot records"); > - error = xfarray_create(descr, max_dquots, > + error = xfarray_create("group dquot records", max_dquots, > sizeof(struct xqcheck_dquot), &xqc->gcounts); > - kfree(descr); > if (error) > goto out_teardown; > } > > if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) { > - descr = xchk_xfile_descr(sc, "project dquot records"); > - error = xfarray_create(descr, max_dquots, > + error = xfarray_create("project dquot records", max_dquots, > sizeof(struct xqcheck_dquot), &xqc->pcounts); > - kfree(descr); > if (error) > goto out_teardown; > } > diff --git a/fs/xfs/scrub/refcount_repair.c b/fs/xfs/scrub/refcount_repair.c > index 9c8cb5332da042..360fd7354880a7 100644 > --- a/fs/xfs/scrub/refcount_repair.c > +++ b/fs/xfs/scrub/refcount_repair.c > @@ -123,13 +123,7 @@ int > xrep_setup_ag_refcountbt( > struct xfs_scrub *sc) > { > - char *descr; > - int error; > - > - descr = xchk_xfile_ag_descr(sc, "rmap record bag"); > - error = xrep_setup_xfbtree(sc, descr); > - kfree(descr); > - return error; > + return xrep_setup_xfbtree(sc, "rmap record bag"); > } > > /* Check for any obvious conflicts with this shared/CoW staging extent. */ > @@ -704,7 +698,6 @@ xrep_refcountbt( > { > struct xrep_refc *rr; > struct xfs_mount *mp = sc->mp; > - char *descr; > int error; > > /* We require the rmapbt to rebuild anything. */ > @@ -717,11 +710,9 @@ xrep_refcountbt( > rr->sc = sc; > > /* Set up enough storage to handle one refcount record per block. */ > - descr = xchk_xfile_ag_descr(sc, "reference count records"); > - error = xfarray_create(descr, mp->m_sb.sb_agblocks, > + error = xfarray_create("reference count records", mp->m_sb.sb_agblocks, > sizeof(struct xfs_refcount_irec), > &rr->refcount_records); > - kfree(descr); > if (error) > goto out_rr; > > diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c > index 17d4a38d735cb8..cfd1cf403b37eb 100644 > --- a/fs/xfs/scrub/rmap_repair.c > +++ b/fs/xfs/scrub/rmap_repair.c > @@ -164,14 +164,11 @@ xrep_setup_ag_rmapbt( > struct xfs_scrub *sc) > { > struct xrep_rmap *rr; > - char *descr; > int error; > > xchk_fsgates_enable(sc, XCHK_FSGATES_RMAP); > > - descr = xchk_xfile_ag_descr(sc, "reverse mapping records"); > - error = xrep_setup_xfbtree(sc, descr); > - kfree(descr); > + error = xrep_setup_xfbtree(sc, "reverse mapping records"); > if (error) > return error; > > diff --git a/fs/xfs/scrub/rtbitmap_repair.c b/fs/xfs/scrub/rtbitmap_repair.c > index 203a1a97c5026e..41d6736a529d02 100644 > --- a/fs/xfs/scrub/rtbitmap_repair.c > +++ b/fs/xfs/scrub/rtbitmap_repair.c > @@ -43,7 +43,6 @@ xrep_setup_rtbitmap( > struct xchk_rtbitmap *rtb) > { > struct xfs_mount *mp = sc->mp; > - char *descr; > unsigned long long blocks = mp->m_sb.sb_rbmblocks; > int error; > > @@ -52,9 +51,8 @@ xrep_setup_rtbitmap( > return error; > > /* Create an xfile to hold our reconstructed bitmap. */ > - descr = xchk_xfile_rtgroup_descr(sc, "bitmap file"); > - error = xfile_create(descr, blocks * mp->m_sb.sb_blocksize, &sc->xfile); > - kfree(descr); > + error = xfile_create("realtime bitmap file", > + blocks * mp->m_sb.sb_blocksize, &sc->xfile); > if (error) > return error; > > diff --git a/fs/xfs/scrub/rtrefcount_repair.c b/fs/xfs/scrub/rtrefcount_repair.c > index 983362447826de..b35e39cce7ad5a 100644 > --- a/fs/xfs/scrub/rtrefcount_repair.c > +++ b/fs/xfs/scrub/rtrefcount_repair.c > @@ -128,13 +128,7 @@ int > xrep_setup_rtrefcountbt( > struct xfs_scrub *sc) > { > - char *descr; > - int error; > - > - descr = xchk_xfile_ag_descr(sc, "rmap record bag"); > - error = xrep_setup_xfbtree(sc, descr); > - kfree(descr); > - return error; > + return xrep_setup_xfbtree(sc, "realtime rmap record bag"); > } > > /* Check for any obvious conflicts with this shared/CoW staging extent. */ > @@ -704,7 +698,6 @@ xrep_rtrefcountbt( > { > struct xrep_rtrefc *rr; > struct xfs_mount *mp = sc->mp; > - char *descr; > int error; > > /* We require the rmapbt to rebuild anything. */ > @@ -722,11 +715,9 @@ xrep_rtrefcountbt( > rr->sc = sc; > > /* Set up enough storage to handle one refcount record per rt extent. */ > - descr = xchk_xfile_ag_descr(sc, "reference count records"); > - error = xfarray_create(descr, mp->m_sb.sb_rextents, > - sizeof(struct xfs_refcount_irec), > + error = xfarray_create("realtime reference count records", > + mp->m_sb.sb_rextents, sizeof(struct xfs_refcount_irec), > &rr->refcount_records); > - kfree(descr); > if (error) > goto out_rr; > > diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c > index 7561941a337a1f..749977a66e40ff 100644 > --- a/fs/xfs/scrub/rtrmap_repair.c > +++ b/fs/xfs/scrub/rtrmap_repair.c > @@ -103,14 +103,11 @@ xrep_setup_rtrmapbt( > struct xfs_scrub *sc) > { > struct xrep_rtrmap *rr; > - char *descr; > int error; > > xchk_fsgates_enable(sc, XCHK_FSGATES_RMAP); > > - descr = xchk_xfile_rtgroup_descr(sc, "reverse mapping records"); > - error = xrep_setup_xfbtree(sc, descr); > - kfree(descr); > + error = xrep_setup_xfbtree(sc, "realtime reverse mapping records"); > if (error) > return error; > > diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c > index 4ac679c1bd29cd..fb78cff2ac3a16 100644 > --- a/fs/xfs/scrub/rtsummary.c > +++ b/fs/xfs/scrub/rtsummary.c > @@ -43,7 +43,6 @@ xchk_setup_rtsummary( > struct xfs_scrub *sc) > { > struct xfs_mount *mp = sc->mp; > - char *descr; > struct xchk_rtsummary *rts; > int error; > > @@ -70,10 +69,8 @@ xchk_setup_rtsummary( > * Create an xfile to construct a new rtsummary file. The xfile allows > * us to avoid pinning kernel memory for this purpose. > */ > - descr = xchk_xfile_descr(sc, "realtime summary file"); > - error = xfile_create(descr, XFS_FSB_TO_B(mp, mp->m_rsumblocks), > - &sc->xfile); > - kfree(descr); > + error = xfile_create("realtime summary file", > + XFS_FSB_TO_B(mp, mp->m_rsumblocks), &sc->xfile); > if (error) > return error; > > After applying patches and running the reproducer for ~10 minutes, no issues were triggered. Tested-by: Jiaming Zhang <r772577952@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer 2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong 2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong @ 2026-01-23 7:03 ` Darrick J. Wong 2026-01-23 14:13 ` Christoph Hellwig 2026-01-23 18:23 ` Jiaming Zhang 2026-01-23 7:03 ` [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord Darrick J. Wong ` (2 subsequent siblings) 4 siblings, 2 replies; 16+ messages in thread From: Darrick J. Wong @ 2026-01-23 7:03 UTC (permalink / raw) To: djwong, cem; +Cc: r772577952, stable, linux-xfs, r772577952, hch From: Darrick J. Wong <djwong@kernel.org> Only call the xfarray and xfblob destructor if we have a valid pointer, and be sure to null out that pointer afterwards. Note that this patch fixes a large number of commits, most of which were merged between 6.9 and 6.10. Cc: r772577952@gmail.com Cc: <stable@vger.kernel.org> # v6.12 Fixes: ab97f4b1c03075 ("xfs: repair AGI unlinked inode bucket lists") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> --- fs/xfs/scrub/agheader_repair.c | 8 ++++++-- fs/xfs/scrub/attr_repair.c | 6 ++++-- fs/xfs/scrub/dir_repair.c | 8 ++++++-- fs/xfs/scrub/dirtree.c | 8 ++++++-- fs/xfs/scrub/nlinks.c | 3 ++- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index a2f6a7f71d8396..6e3fef36d6614a 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -837,8 +837,12 @@ xrep_agi_buf_cleanup( { struct xrep_agi *ragi = buf; - xfarray_destroy(ragi->iunlink_prev); - xfarray_destroy(ragi->iunlink_next); + if (ragi->iunlink_prev) + xfarray_destroy(ragi->iunlink_prev); + ragi->iunlink_prev = NULL; + if (ragi->iunlink_next) + xfarray_destroy(ragi->iunlink_next); + ragi->iunlink_next = NULL; xagino_bitmap_destroy(&ragi->iunlink_bmp); } diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c index eded354dec11ee..dd24044c44efd3 100644 --- a/fs/xfs/scrub/attr_repair.c +++ b/fs/xfs/scrub/attr_repair.c @@ -1516,8 +1516,10 @@ xrep_xattr_teardown( xfblob_destroy(rx->pptr_names); if (rx->pptr_recs) xfarray_destroy(rx->pptr_recs); - xfblob_destroy(rx->xattr_blobs); - xfarray_destroy(rx->xattr_records); + if (rx->xattr_blobs) + xfblob_destroy(rx->xattr_blobs); + if (rx->xattr_records) + xfarray_destroy(rx->xattr_records); mutex_destroy(&rx->lock); kfree(rx); } diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index 7a21b688a47158..d5a55eabf68012 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -172,8 +172,12 @@ xrep_dir_teardown( struct xrep_dir *rd = sc->buf; xrep_findparent_scan_teardown(&rd->pscan); - xfblob_destroy(rd->dir_names); - xfarray_destroy(rd->dir_entries); + if (rd->dir_names) + xfblob_destroy(rd->dir_names); + rd->dir_names = NULL; + if (rd->dir_entries) + xfarray_destroy(rd->dir_entries); + rd->dir_names = NULL; } /* Set up for a directory repair. */ diff --git a/fs/xfs/scrub/dirtree.c b/fs/xfs/scrub/dirtree.c index f9c85b8b194fa4..3e0bbe75c44cff 100644 --- a/fs/xfs/scrub/dirtree.c +++ b/fs/xfs/scrub/dirtree.c @@ -81,8 +81,12 @@ xchk_dirtree_buf_cleanup( kfree(path); } - xfblob_destroy(dl->path_names); - xfarray_destroy(dl->path_steps); + if (dl->path_names) + xfblob_destroy(dl->path_names); + dl->path_names = NULL; + if (dl->path_steps) + xfarray_destroy(dl->path_steps); + dl->path_steps = NULL; mutex_destroy(&dl->lock); } diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c index 2ba686e4de8bc5..dec3b9b47453ea 100644 --- a/fs/xfs/scrub/nlinks.c +++ b/fs/xfs/scrub/nlinks.c @@ -971,7 +971,8 @@ xchk_nlinks_teardown_scan( xfs_dir_hook_del(xnc->sc->mp, &xnc->dhook); - xfarray_destroy(xnc->nlinks); + if (xnc->nlinks) + xfarray_destroy(xnc->nlinks); xnc->nlinks = NULL; xchk_iscan_teardown(&xnc->collect_iscan); ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer 2026-01-23 7:03 ` [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer Darrick J. Wong @ 2026-01-23 14:13 ` Christoph Hellwig 2026-01-23 18:23 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Christoph Hellwig @ 2026-01-23 14:13 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, r772577952, stable, linux-xfs, hch On Thu, Jan 22, 2026 at 11:03:37PM -0800, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@kernel.org> > > Only call the xfarray and xfblob destructor if we have a valid pointer, > and be sure to null out that pointer afterwards. Note that this patch > fixes a large number of commits, most of which were merged between 6.9 > and 6.10. Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer 2026-01-23 7:03 ` [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer Darrick J. Wong 2026-01-23 14:13 ` Christoph Hellwig @ 2026-01-23 18:23 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Jiaming Zhang @ 2026-01-23 18:23 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, stable, linux-xfs, hch Darrick J. Wong <djwong@kernel.org> 于2026年1月23日周五 15:03写道: > > From: Darrick J. Wong <djwong@kernel.org> > > Only call the xfarray and xfblob destructor if we have a valid pointer, > and be sure to null out that pointer afterwards. Note that this patch > fixes a large number of commits, most of which were merged between 6.9 > and 6.10. > > Cc: r772577952@gmail.com > Cc: <stable@vger.kernel.org> # v6.12 > Fixes: ab97f4b1c03075 ("xfs: repair AGI unlinked inode bucket lists") > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > --- > fs/xfs/scrub/agheader_repair.c | 8 ++++++-- > fs/xfs/scrub/attr_repair.c | 6 ++++-- > fs/xfs/scrub/dir_repair.c | 8 ++++++-- > fs/xfs/scrub/dirtree.c | 8 ++++++-- > fs/xfs/scrub/nlinks.c | 3 ++- > 5 files changed, 24 insertions(+), 9 deletions(-) > > > diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c > index a2f6a7f71d8396..6e3fef36d6614a 100644 > --- a/fs/xfs/scrub/agheader_repair.c > +++ b/fs/xfs/scrub/agheader_repair.c > @@ -837,8 +837,12 @@ xrep_agi_buf_cleanup( > { > struct xrep_agi *ragi = buf; > > - xfarray_destroy(ragi->iunlink_prev); > - xfarray_destroy(ragi->iunlink_next); > + if (ragi->iunlink_prev) > + xfarray_destroy(ragi->iunlink_prev); > + ragi->iunlink_prev = NULL; > + if (ragi->iunlink_next) > + xfarray_destroy(ragi->iunlink_next); > + ragi->iunlink_next = NULL; > xagino_bitmap_destroy(&ragi->iunlink_bmp); > } > > diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c > index eded354dec11ee..dd24044c44efd3 100644 > --- a/fs/xfs/scrub/attr_repair.c > +++ b/fs/xfs/scrub/attr_repair.c > @@ -1516,8 +1516,10 @@ xrep_xattr_teardown( > xfblob_destroy(rx->pptr_names); > if (rx->pptr_recs) > xfarray_destroy(rx->pptr_recs); > - xfblob_destroy(rx->xattr_blobs); > - xfarray_destroy(rx->xattr_records); > + if (rx->xattr_blobs) > + xfblob_destroy(rx->xattr_blobs); > + if (rx->xattr_records) > + xfarray_destroy(rx->xattr_records); > mutex_destroy(&rx->lock); > kfree(rx); > } > diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c > index 7a21b688a47158..d5a55eabf68012 100644 > --- a/fs/xfs/scrub/dir_repair.c > +++ b/fs/xfs/scrub/dir_repair.c > @@ -172,8 +172,12 @@ xrep_dir_teardown( > struct xrep_dir *rd = sc->buf; > > xrep_findparent_scan_teardown(&rd->pscan); > - xfblob_destroy(rd->dir_names); > - xfarray_destroy(rd->dir_entries); > + if (rd->dir_names) > + xfblob_destroy(rd->dir_names); > + rd->dir_names = NULL; > + if (rd->dir_entries) > + xfarray_destroy(rd->dir_entries); > + rd->dir_names = NULL; > } > > /* Set up for a directory repair. */ > diff --git a/fs/xfs/scrub/dirtree.c b/fs/xfs/scrub/dirtree.c > index f9c85b8b194fa4..3e0bbe75c44cff 100644 > --- a/fs/xfs/scrub/dirtree.c > +++ b/fs/xfs/scrub/dirtree.c > @@ -81,8 +81,12 @@ xchk_dirtree_buf_cleanup( > kfree(path); > } > > - xfblob_destroy(dl->path_names); > - xfarray_destroy(dl->path_steps); > + if (dl->path_names) > + xfblob_destroy(dl->path_names); > + dl->path_names = NULL; > + if (dl->path_steps) > + xfarray_destroy(dl->path_steps); > + dl->path_steps = NULL; > mutex_destroy(&dl->lock); > } > > diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c > index 2ba686e4de8bc5..dec3b9b47453ea 100644 > --- a/fs/xfs/scrub/nlinks.c > +++ b/fs/xfs/scrub/nlinks.c > @@ -971,7 +971,8 @@ xchk_nlinks_teardown_scan( > > xfs_dir_hook_del(xnc->sc->mp, &xnc->dhook); > > - xfarray_destroy(xnc->nlinks); > + if (xnc->nlinks) > + xfarray_destroy(xnc->nlinks); > xnc->nlinks = NULL; > > xchk_iscan_teardown(&xnc->collect_iscan); > After applying patches and running the reproducer for ~10 minutes, no issues were triggered. Tested-by: Jiaming Zhang <r772577952@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord 2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong 2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong 2026-01-23 7:03 ` [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer Darrick J. Wong @ 2026-01-23 7:03 ` Darrick J. Wong 2026-01-23 14:14 ` Christoph Hellwig 2026-01-23 18:24 ` Jiaming Zhang 2026-01-23 7:04 ` [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner Darrick J. Wong 2026-01-23 7:04 ` [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees Darrick J. Wong 4 siblings, 2 replies; 16+ messages in thread From: Darrick J. Wong @ 2026-01-23 7:03 UTC (permalink / raw) To: djwong, cem; +Cc: hch, r772577952, stable, linux-xfs, r772577952, hch From: Darrick J. Wong <djwong@kernel.org> Fix this function to return NULL instead of a mangled ENOMEM, then fix the callers to actually check for a null pointer and return ENOMEM. Most of the corrections here are for code merged between 6.2 and 6.10. Cc: r772577952@gmail.com Cc: <stable@vger.kernel.org> # v6.12 Fixes: 1a5f6e08d4e379 ("xfs: create subordinate scrub contexts for xchk_metadata_inode_subtype") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/scrub/common.c | 3 +++ fs/xfs/scrub/repair.c | 3 +++ fs/xfs/scrub/scrub.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index 5f9be4151d722e..ebabf3b620a2cf 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -1399,6 +1399,9 @@ xchk_metadata_inode_subtype( int error; sub = xchk_scrub_create_subord(sc, scrub_type); + if (!sub) + return -ENOMEM; + error = sub->sc.ops->scrub(&sub->sc); xchk_scrub_free_subord(sub); return error; diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c index efd5a7ccdf624a..4d45d39e67f11e 100644 --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c @@ -1136,6 +1136,9 @@ xrep_metadata_inode_subtype( * setup/teardown routines. */ sub = xchk_scrub_create_subord(sc, scrub_type); + if (!sub) + return -ENOMEM; + error = sub->sc.ops->scrub(&sub->sc); if (error) goto out; diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 3c3b0d25006ff4..c312f0a672e65f 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -634,7 +634,7 @@ xchk_scrub_create_subord( sub = kzalloc(sizeof(*sub), XCHK_GFP_FLAGS); if (!sub) - return ERR_PTR(-ENOMEM); + return NULL; sub->old_smtype = sc->sm->sm_type; sub->old_smflags = sc->sm->sm_flags; ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord 2026-01-23 7:03 ` [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord Darrick J. Wong @ 2026-01-23 14:14 ` Christoph Hellwig 2026-01-23 18:24 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Christoph Hellwig @ 2026-01-23 14:14 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, hch, r772577952, stable, linux-xfs Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord 2026-01-23 7:03 ` [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord Darrick J. Wong 2026-01-23 14:14 ` Christoph Hellwig @ 2026-01-23 18:24 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Jiaming Zhang @ 2026-01-23 18:24 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, hch, stable, linux-xfs Darrick J. Wong <djwong@kernel.org> 于2026年1月23日周五 15:03写道: > > From: Darrick J. Wong <djwong@kernel.org> > > Fix this function to return NULL instead of a mangled ENOMEM, then fix > the callers to actually check for a null pointer and return ENOMEM. > Most of the corrections here are for code merged between 6.2 and 6.10. > > Cc: r772577952@gmail.com > Cc: <stable@vger.kernel.org> # v6.12 > Fixes: 1a5f6e08d4e379 ("xfs: create subordinate scrub contexts for xchk_metadata_inode_subtype") > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > Reviewed-by: Christoph Hellwig <hch@lst.de> > --- > fs/xfs/scrub/common.c | 3 +++ > fs/xfs/scrub/repair.c | 3 +++ > fs/xfs/scrub/scrub.c | 2 +- > 3 files changed, 7 insertions(+), 1 deletion(-) > > > diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c > index 5f9be4151d722e..ebabf3b620a2cf 100644 > --- a/fs/xfs/scrub/common.c > +++ b/fs/xfs/scrub/common.c > @@ -1399,6 +1399,9 @@ xchk_metadata_inode_subtype( > int error; > > sub = xchk_scrub_create_subord(sc, scrub_type); > + if (!sub) > + return -ENOMEM; > + > error = sub->sc.ops->scrub(&sub->sc); > xchk_scrub_free_subord(sub); > return error; > diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c > index efd5a7ccdf624a..4d45d39e67f11e 100644 > --- a/fs/xfs/scrub/repair.c > +++ b/fs/xfs/scrub/repair.c > @@ -1136,6 +1136,9 @@ xrep_metadata_inode_subtype( > * setup/teardown routines. > */ > sub = xchk_scrub_create_subord(sc, scrub_type); > + if (!sub) > + return -ENOMEM; > + > error = sub->sc.ops->scrub(&sub->sc); > if (error) > goto out; > diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c > index 3c3b0d25006ff4..c312f0a672e65f 100644 > --- a/fs/xfs/scrub/scrub.c > +++ b/fs/xfs/scrub/scrub.c > @@ -634,7 +634,7 @@ xchk_scrub_create_subord( > > sub = kzalloc(sizeof(*sub), XCHK_GFP_FLAGS); > if (!sub) > - return ERR_PTR(-ENOMEM); > + return NULL; > > sub->old_smtype = sc->sm->sm_type; > sub->old_smflags = sc->sm->sm_flags; > After applying patches and running the reproducer for ~10 minutes, no issues were triggered. Tested-by: Jiaming Zhang <r772577952@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner 2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong ` (2 preceding siblings ...) 2026-01-23 7:03 ` [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord Darrick J. Wong @ 2026-01-23 7:04 ` Darrick J. Wong 2026-01-23 14:14 ` Christoph Hellwig 2026-01-23 18:24 ` Jiaming Zhang 2026-01-23 7:04 ` [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees Darrick J. Wong 4 siblings, 2 replies; 16+ messages in thread From: Darrick J. Wong @ 2026-01-23 7:04 UTC (permalink / raw) To: djwong, cem; +Cc: hch, r772577952, stable, linux-xfs, r772577952, hch From: Darrick J. Wong <djwong@kernel.org> We cannot dereference bs->cur when trying to determine if bs->cur aliases bs->sc->sa.{bno,rmap}_cur after the latter has been freed. Fix this by sampling before type before any freeing could happen. The correct temporal ordering was broken when we removed xfs_btnum_t. Cc: r772577952@gmail.com Cc: <stable@vger.kernel.org> # v6.9 Fixes: ec793e690f801d ("xfs: remove xfs_btnum_t") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/scrub/btree.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c index c440f2eb4d1a44..b497f6a474c778 100644 --- a/fs/xfs/scrub/btree.c +++ b/fs/xfs/scrub/btree.c @@ -372,12 +372,15 @@ xchk_btree_check_block_owner( { xfs_agnumber_t agno; xfs_agblock_t agbno; + bool is_bnobt, is_rmapbt; bool init_sa; int error = 0; if (!bs->cur) return 0; + is_bnobt = xfs_btree_is_bno(bs->cur->bc_ops); + is_rmapbt = xfs_btree_is_rmap(bs->cur->bc_ops); agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); agbno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); @@ -400,11 +403,11 @@ xchk_btree_check_block_owner( * have to nullify it (to shut down further block owner checks) if * self-xref encounters problems. */ - if (!bs->sc->sa.bno_cur && xfs_btree_is_bno(bs->cur->bc_ops)) + if (!bs->sc->sa.bno_cur && is_bnobt) bs->cur = NULL; xchk_xref_is_only_owned_by(bs->sc, agbno, 1, bs->oinfo); - if (!bs->sc->sa.rmap_cur && xfs_btree_is_rmap(bs->cur->bc_ops)) + if (!bs->sc->sa.rmap_cur && is_rmapbt) bs->cur = NULL; out_free: ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner 2026-01-23 7:04 ` [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner Darrick J. Wong @ 2026-01-23 14:14 ` Christoph Hellwig 2026-01-23 18:24 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Christoph Hellwig @ 2026-01-23 14:14 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, hch, r772577952, stable, linux-xfs On Thu, Jan 22, 2026 at 11:04:08PM -0800, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@kernel.org> > > We cannot dereference bs->cur when trying to determine if bs->cur > aliases bs->sc->sa.{bno,rmap}_cur after the latter has been freed. > Fix this by sampling before type before any freeing could happen. > The correct temporal ordering was broken when we removed xfs_btnum_t. Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner 2026-01-23 7:04 ` [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner Darrick J. Wong 2026-01-23 14:14 ` Christoph Hellwig @ 2026-01-23 18:24 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Jiaming Zhang @ 2026-01-23 18:24 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, hch, stable, linux-xfs Darrick J. Wong <djwong@kernel.org> 于2026年1月23日周五 15:04写道: > > From: Darrick J. Wong <djwong@kernel.org> > > We cannot dereference bs->cur when trying to determine if bs->cur > aliases bs->sc->sa.{bno,rmap}_cur after the latter has been freed. > Fix this by sampling before type before any freeing could happen. > The correct temporal ordering was broken when we removed xfs_btnum_t. > > Cc: r772577952@gmail.com > Cc: <stable@vger.kernel.org> # v6.9 > Fixes: ec793e690f801d ("xfs: remove xfs_btnum_t") > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > Reviewed-by: Christoph Hellwig <hch@lst.de> > --- > fs/xfs/scrub/btree.c | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > > diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c > index c440f2eb4d1a44..b497f6a474c778 100644 > --- a/fs/xfs/scrub/btree.c > +++ b/fs/xfs/scrub/btree.c > @@ -372,12 +372,15 @@ xchk_btree_check_block_owner( > { > xfs_agnumber_t agno; > xfs_agblock_t agbno; > + bool is_bnobt, is_rmapbt; > bool init_sa; > int error = 0; > > if (!bs->cur) > return 0; > > + is_bnobt = xfs_btree_is_bno(bs->cur->bc_ops); > + is_rmapbt = xfs_btree_is_rmap(bs->cur->bc_ops); > agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); > agbno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); > > @@ -400,11 +403,11 @@ xchk_btree_check_block_owner( > * have to nullify it (to shut down further block owner checks) if > * self-xref encounters problems. > */ > - if (!bs->sc->sa.bno_cur && xfs_btree_is_bno(bs->cur->bc_ops)) > + if (!bs->sc->sa.bno_cur && is_bnobt) > bs->cur = NULL; > > xchk_xref_is_only_owned_by(bs->sc, agbno, 1, bs->oinfo); > - if (!bs->sc->sa.rmap_cur && xfs_btree_is_rmap(bs->cur->bc_ops)) > + if (!bs->sc->sa.rmap_cur && is_rmapbt) > bs->cur = NULL; > > out_free: > After applying patches and running the reproducer for ~10 minutes, no issues were triggered. Tested-by: Jiaming Zhang <r772577952@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees 2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong ` (3 preceding siblings ...) 2026-01-23 7:04 ` [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner Darrick J. Wong @ 2026-01-23 7:04 ` Darrick J. Wong 2026-01-23 14:16 ` Christoph Hellwig 2026-01-23 18:25 ` Jiaming Zhang 4 siblings, 2 replies; 16+ messages in thread From: Darrick J. Wong @ 2026-01-23 7:04 UTC (permalink / raw) To: djwong, cem; +Cc: r772577952, stable, linux-xfs, r772577952, hch From: Darrick J. Wong <djwong@kernel.org> The free space and inode btree repair functions will rebuild both btrees at the same time, after which it needs to evaluate both btrees to confirm that the corruptions are gone. However, Jiaming Zhang ran syzbot and produced a crash in the second xchk_allocbt call. His root-cause analysis is as follows (with minor corrections): In xrep_revalidate_allocbt(), xchk_allocbt() is called twice (first for BNOBT, second for CNTBT). The cause of this issue is that the first call nullified the cursor required by the second call. Let's first enter xrep_revalidate_allocbt() via following call chain: xfs_file_ioctl() -> xfs_ioc_scrubv_metadata() -> xfs_scrub_metadata() -> `sc->ops->repair_eval(sc)` -> xrep_revalidate_allocbt() xchk_allocbt() is called twice in this function. In the first call: /* Note that sc->sm->sm_type is XFS_SCRUB_TYPE_BNOPT now */ xchk_allocbt() -> xchk_btree() -> `bs->scrub_rec(bs, recp)` -> xchk_allocbt_rec() -> xchk_allocbt_xref() -> xchk_allocbt_xref_other() since sm_type is XFS_SCRUB_TYPE_BNOBT, pur is set to &sc->sa.cnt_cur. Kernel called xfs_alloc_get_rec() and returned -EFSCORRUPTED. Call chain: xfs_alloc_get_rec() -> xfs_btree_get_rec() -> xfs_btree_check_block() -> (XFS_IS_CORRUPT || XFS_TEST_ERROR), the former is false and the latter is true, return -EFSCORRUPTED. This should be caused by ioctl$XFS_IOC_ERROR_INJECTION I guess. Back to xchk_allocbt_xref_other(), after receiving -EFSCORRUPTED from xfs_alloc_get_rec(), kernel called xchk_should_check_xref(). In this function, *curpp (points to sc->sa.cnt_cur) is nullified. Back to xrep_revalidate_allocbt(), since sc->sa.cnt_cur has been nullified, it then triggered null-ptr-deref via xchk_allocbt() (second call) -> xchk_btree(). So. The bnobt revalidation failed on a cross-reference attempt, so we deleted the cntbt cursor, and then crashed when we tried to revalidate the cntbt. Therefore, check for a null cntbt cursor before that revalidation, and mark the repair incomplete. Also we can ignore the second tree entirely if the first tree was rebuilt but is already corrupt. Apply the same fix to xrep_revalidate_iallocbt because it has the same problem. Cc: r772577952@gmail.com Link: https://lore.kernel.org/linux-xfs/CANypQFYU5rRPkTy=iG5m1Lp4RWasSgrHXAh3p8YJojxV0X15dQ@mail.gmail.com/T/#m520c7835fad637eccf843c7936c200589427cc7e Cc: <stable@vger.kernel.org> # v6.8 Fixes: dbfbf3bdf639a2 ("xfs: repair inode btrees") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> --- fs/xfs/scrub/alloc_repair.c | 15 +++++++++++++++ fs/xfs/scrub/ialloc_repair.c | 20 +++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/fs/xfs/scrub/alloc_repair.c b/fs/xfs/scrub/alloc_repair.c index b6fe1f23819eb2..35035d02a23163 100644 --- a/fs/xfs/scrub/alloc_repair.c +++ b/fs/xfs/scrub/alloc_repair.c @@ -923,7 +923,22 @@ xrep_revalidate_allocbt( if (error) goto out; + /* + * If the bnobt is still corrupt, we've failed to repair the filesystem + * and should just bail out. + * + * If the bnobt fails cross-examination with the cntbt, the scan will + * free the cntbt cursor, so we need to mark the repair incomplete + * and avoid walking off the end of the NULL cntbt cursor. + */ + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + goto out; + sc->sm->sm_type = XFS_SCRUB_TYPE_CNTBT; + if (!sc->sa.cnt_cur) { + xchk_set_incomplete(sc); + goto out; + } error = xchk_allocbt(sc); out: sc->sm->sm_type = old_type; diff --git a/fs/xfs/scrub/ialloc_repair.c b/fs/xfs/scrub/ialloc_repair.c index b1d00167d263f4..f28459f58832f4 100644 --- a/fs/xfs/scrub/ialloc_repair.c +++ b/fs/xfs/scrub/ialloc_repair.c @@ -863,10 +863,24 @@ xrep_revalidate_iallocbt( if (error) goto out; - if (xfs_has_finobt(sc->mp)) { - sc->sm->sm_type = XFS_SCRUB_TYPE_FINOBT; - error = xchk_iallocbt(sc); + /* + * If the inobt is still corrupt, we've failed to repair the filesystem + * and should just bail out. + * + * If the inobt fails cross-examination with the finobt, the scan will + * free the finobt cursor, so we need to mark the repair incomplete + * and avoid walking off the end of the NULL finobt cursor. + */ + if (!xfs_has_finobt(sc->mp) || + (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) + goto out; + + sc->sm->sm_type = XFS_SCRUB_TYPE_FINOBT; + if (!sc->sa.fino_cur) { + xchk_set_incomplete(sc); + goto out; } + error = xchk_iallocbt(sc); out: sc->sm->sm_type = old_type; ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees 2026-01-23 7:04 ` [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees Darrick J. Wong @ 2026-01-23 14:16 ` Christoph Hellwig 2026-01-23 18:25 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Christoph Hellwig @ 2026-01-23 14:16 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, r772577952, stable, linux-xfs, hch Looks good: Reviewed-by: Christoph Hellwig <hch@lst.de> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees 2026-01-23 7:04 ` [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees Darrick J. Wong 2026-01-23 14:16 ` Christoph Hellwig @ 2026-01-23 18:25 ` Jiaming Zhang 1 sibling, 0 replies; 16+ messages in thread From: Jiaming Zhang @ 2026-01-23 18:25 UTC (permalink / raw) To: Darrick J. Wong; +Cc: cem, stable, linux-xfs, hch Darrick J. Wong <djwong@kernel.org> 于2026年1月23日周五 15:04写道: > > From: Darrick J. Wong <djwong@kernel.org> > > The free space and inode btree repair functions will rebuild both btrees > at the same time, after which it needs to evaluate both btrees to > confirm that the corruptions are gone. > > However, Jiaming Zhang ran syzbot and produced a crash in the second > xchk_allocbt call. His root-cause analysis is as follows (with minor > corrections): > > In xrep_revalidate_allocbt(), xchk_allocbt() is called twice (first > for BNOBT, second for CNTBT). The cause of this issue is that the > first call nullified the cursor required by the second call. > > Let's first enter xrep_revalidate_allocbt() via following call chain: > > xfs_file_ioctl() -> > xfs_ioc_scrubv_metadata() -> > xfs_scrub_metadata() -> > `sc->ops->repair_eval(sc)` -> > xrep_revalidate_allocbt() > > xchk_allocbt() is called twice in this function. In the first call: > > /* Note that sc->sm->sm_type is XFS_SCRUB_TYPE_BNOPT now */ > xchk_allocbt() -> > xchk_btree() -> > `bs->scrub_rec(bs, recp)` -> > xchk_allocbt_rec() -> > xchk_allocbt_xref() -> > xchk_allocbt_xref_other() > > since sm_type is XFS_SCRUB_TYPE_BNOBT, pur is set to &sc->sa.cnt_cur. > Kernel called xfs_alloc_get_rec() and returned -EFSCORRUPTED. Call > chain: > > xfs_alloc_get_rec() -> > xfs_btree_get_rec() -> > xfs_btree_check_block() -> > (XFS_IS_CORRUPT || XFS_TEST_ERROR), the former is false and the latter > is true, return -EFSCORRUPTED. This should be caused by > ioctl$XFS_IOC_ERROR_INJECTION I guess. > > Back to xchk_allocbt_xref_other(), after receiving -EFSCORRUPTED from > xfs_alloc_get_rec(), kernel called xchk_should_check_xref(). In this > function, *curpp (points to sc->sa.cnt_cur) is nullified. > > Back to xrep_revalidate_allocbt(), since sc->sa.cnt_cur has been > nullified, it then triggered null-ptr-deref via xchk_allocbt() (second > call) -> xchk_btree(). > > So. The bnobt revalidation failed on a cross-reference attempt, so we > deleted the cntbt cursor, and then crashed when we tried to revalidate > the cntbt. Therefore, check for a null cntbt cursor before that > revalidation, and mark the repair incomplete. Also we can ignore the > second tree entirely if the first tree was rebuilt but is already > corrupt. > > Apply the same fix to xrep_revalidate_iallocbt because it has the same > problem. > > Cc: r772577952@gmail.com > Link: https://lore.kernel.org/linux-xfs/CANypQFYU5rRPkTy=iG5m1Lp4RWasSgrHXAh3p8YJojxV0X15dQ@mail.gmail.com/T/#m520c7835fad637eccf843c7936c200589427cc7e > Cc: <stable@vger.kernel.org> # v6.8 > Fixes: dbfbf3bdf639a2 ("xfs: repair inode btrees") > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > --- > fs/xfs/scrub/alloc_repair.c | 15 +++++++++++++++ > fs/xfs/scrub/ialloc_repair.c | 20 +++++++++++++++++--- > 2 files changed, 32 insertions(+), 3 deletions(-) > > > diff --git a/fs/xfs/scrub/alloc_repair.c b/fs/xfs/scrub/alloc_repair.c > index b6fe1f23819eb2..35035d02a23163 100644 > --- a/fs/xfs/scrub/alloc_repair.c > +++ b/fs/xfs/scrub/alloc_repair.c > @@ -923,7 +923,22 @@ xrep_revalidate_allocbt( > if (error) > goto out; > > + /* > + * If the bnobt is still corrupt, we've failed to repair the filesystem > + * and should just bail out. > + * > + * If the bnobt fails cross-examination with the cntbt, the scan will > + * free the cntbt cursor, so we need to mark the repair incomplete > + * and avoid walking off the end of the NULL cntbt cursor. > + */ > + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) > + goto out; > + > sc->sm->sm_type = XFS_SCRUB_TYPE_CNTBT; > + if (!sc->sa.cnt_cur) { > + xchk_set_incomplete(sc); > + goto out; > + } > error = xchk_allocbt(sc); > out: > sc->sm->sm_type = old_type; > diff --git a/fs/xfs/scrub/ialloc_repair.c b/fs/xfs/scrub/ialloc_repair.c > index b1d00167d263f4..f28459f58832f4 100644 > --- a/fs/xfs/scrub/ialloc_repair.c > +++ b/fs/xfs/scrub/ialloc_repair.c > @@ -863,10 +863,24 @@ xrep_revalidate_iallocbt( > if (error) > goto out; > > - if (xfs_has_finobt(sc->mp)) { > - sc->sm->sm_type = XFS_SCRUB_TYPE_FINOBT; > - error = xchk_iallocbt(sc); > + /* > + * If the inobt is still corrupt, we've failed to repair the filesystem > + * and should just bail out. > + * > + * If the inobt fails cross-examination with the finobt, the scan will > + * free the finobt cursor, so we need to mark the repair incomplete > + * and avoid walking off the end of the NULL finobt cursor. > + */ > + if (!xfs_has_finobt(sc->mp) || > + (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) > + goto out; > + > + sc->sm->sm_type = XFS_SCRUB_TYPE_FINOBT; > + if (!sc->sa.fino_cur) { > + xchk_set_incomplete(sc); > + goto out; > } > + error = xchk_iallocbt(sc); > > out: > sc->sm->sm_type = old_type; > After applying patches and running the reproducer for ~10 minutes, no issues were triggered. Tested-by: Jiaming Zhang <r772577952@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-01-23 18:26 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-23 7:00 [PATCHSET 3/3] xfs: syzbot fixes for online fsck Darrick J. Wong
2026-01-23 7:03 ` [PATCH 1/5] xfs: get rid of the xchk_xfile_*_descr calls Darrick J. Wong
2026-01-23 14:13 ` Christoph Hellwig
2026-01-23 18:22 ` Jiaming Zhang
2026-01-23 7:03 ` [PATCH 2/5] xfs: only call xf{array,blob}_destroy if we have a valid pointer Darrick J. Wong
2026-01-23 14:13 ` Christoph Hellwig
2026-01-23 18:23 ` Jiaming Zhang
2026-01-23 7:03 ` [PATCH 3/5] xfs: check return value of xchk_scrub_create_subord Darrick J. Wong
2026-01-23 14:14 ` Christoph Hellwig
2026-01-23 18:24 ` Jiaming Zhang
2026-01-23 7:04 ` [PATCH 4/5] xfs: fix UAF in xchk_btree_check_block_owner Darrick J. Wong
2026-01-23 14:14 ` Christoph Hellwig
2026-01-23 18:24 ` Jiaming Zhang
2026-01-23 7:04 ` [PATCH 5/5] xfs: check for deleted cursors when revalidating two btrees Darrick J. Wong
2026-01-23 14:16 ` Christoph Hellwig
2026-01-23 18:25 ` Jiaming Zhang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox