[PATCH 6.12 293/460] xfs: get rid of the xchk_xfile_*_descr calls

Greg Kroah-Hartman
2026-03-23T14:45:50Z

6.12-stable review patch. If anyone has any objections, please let me know.

------------------

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

[ Upstream commit 60382993a2e18041f88c7969f567f168cd3b4de3 ]

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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Jiaming Zhang <r772577952@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
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/common.h | 18 ------------------
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/rtsummary.c | 7 ++-----
16 files changed, 41 insertions(+), 139 deletions(-)

--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -1720,7 +1720,6 @@ xrep_agi(
{
struct xrep_agi *ragi;
struct xfs_mount *mp = sc->mp;
- char *descr;
unsigned int i;
int error;

@@ -1754,17 +1753,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;

--- a/fs/xfs/scrub/alloc_repair.c
+++ b/fs/xfs/scrub/alloc_repair.c
@@ -849,7 +849,6 @@ xrep_allocbt(
{
struct xrep_abt *ra;
struct xfs_mount *mp = sc->mp;
- char *descr;
int error;

/* We require the rmapbt to rebuild anything. */
@@ -875,11 +874,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;

--- a/fs/xfs/scrub/attr_repair.c
+++ b/fs/xfs/scrub/attr_repair.c
@@ -1531,7 +1531,6 @@ xrep_xattr_setup_scan(
struct xrep_xattr **rxp)
{
struct xrep_xattr *rx;
- char *descr;
int max_len;
int error;

@@ -1557,35 +1556,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;

--- a/fs/xfs/scrub/bmap_repair.c
+++ b/fs/xfs/scrub/bmap_repair.c
@@ -800,7 +800,6 @@ xrep_bmap(
bool allow_unwritten)
{
struct xrep_bmap *rb;
- char *descr;
xfs_extnum_t max_bmbt_recs;
bool large_extcount;
int error = 0;
@@ -822,11 +821,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;

--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -202,24 +202,6 @@ static inline bool xchk_could_repair(con
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 ? (sc)->sa.pag->pag_agno : (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__)
-
-/*
* 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
* up, and again to tear it down. These costs add up quickly, so we only want
--- a/fs/xfs/scrub/dir.c
+++ b/fs/xfs/scrub/dir.c
@@ -1094,22 +1094,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;
}
--- a/fs/xfs/scrub/dir_repair.c
+++ b/fs/xfs/scrub/dir_repair.c
@@ -1782,20 +1782,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;

--- a/fs/xfs/scrub/dirtree.c
+++ b/fs/xfs/scrub/dirtree.c
@@ -96,7 +96,6 @@ xchk_setup_dirtree(
struct xfs_scrub *sc)
{
struct xchk_dirtree *dl;
- char *descr;
int error;

xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS);
@@ -120,16 +119,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;

--- a/fs/xfs/scrub/ialloc_repair.c
+++ b/fs/xfs/scrub/ialloc_repair.c
@@ -804,7 +804,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;

@@ -823,11 +822,9 @@ xrep_iallocbt(
/* Set up enough storage to handle an AG with nothing but inodes. */
xfs_agino_range(mp, sc->sa.pag->pag_agno, &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;

--- a/fs/xfs/scrub/nlinks.c
+++ b/fs/xfs/scrub/nlinks.c
@@ -995,7 +995,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;
@@ -1012,10 +1011,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;

--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -733,7 +733,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);
@@ -746,16 +745,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;

--- a/fs/xfs/scrub/parent_repair.c
+++ b/fs/xfs/scrub/parent_repair.c
@@ -1476,7 +1476,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;
@@ -1504,32 +1503,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;

--- 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;
}
--- 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. */
@@ -705,7 +699,6 @@ xrep_refcountbt(
{
struct xrep_refc *rr;
struct xfs_mount *mp = sc->mp;
- char *descr;
int error;

/* We require the rmapbt to rebuild anything. */
@@ -718,11 +711,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;

--- a/fs/xfs/scrub/rmap_repair.c
+++ b/fs/xfs/scrub/rmap_repair.c
@@ -161,14 +161,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;

--- a/fs/xfs/scrub/rtsummary.c
+++ b/fs/xfs/scrub/rtsummary.c
@@ -42,7 +42,6 @@ xchk_setup_rtsummary(
struct xfs_scrub *sc)
{
struct xfs_mount *mp = sc->mp;
- char *descr;
struct xchk_rtsummary *rts;
int error;

@@ -62,10 +61,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;