[PATCH v3] xfs: fix heap buffer overflow in xfs_bmbt_to_bmdr
Hongling Zeng <[email protected]> Thu, 30 Jul 2026 17:48:24 +0800
| Newsgroups | org.kernel.vger.linux-xfs,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
The xfs_bmbt_to_bmdr() function converts an in-memory btree root to on-disk form during log recovery. It uses bb_numrecs from the source to determine memcpy size without validating against the destination fork capacity. Current code: dmxr = xfs_bmdr_maxrecs(dblocklen, 0); // destination capacity ... dmxr = be16_to_cpu(dblock->bb_numrecs); // overwrite with source value! memcpy(..., * dmxr); // may overflow destination! If bb_numrecs is larger than the destination fork capacity, memcpy writes beyond the fork buffer, causing heap overflow. Fix by validating bb_numrecs against the destination capacity before using it for memcpy operations. Cc: [email protected] Fixes: 8ea5682d0711 ("xfs: refactor log recovery item dispatch for pass2 readhead functions") Signed-off-by: Hongling Zeng <[email protected]> --- Change in v3: - Use dmxr for tpp calculation (on-disk format) and nrecs for memcpy (actual records) --- Change in v2: - Ensure memcpy operations consistently use nrecs instead of dmxr. --- fs/xfs/libxfs/xfs_bmap_btree.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 758a4b1ccf5b..a119053d67b5 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -151,6 +151,7 @@ xfs_bmbt_to_bmdr( int dmxr; xfs_bmbt_key_t *fkp; __be64 *fpp; + int nrecs; xfs_bmbt_key_t *tkp; __be64 *tpp; @@ -167,14 +168,19 @@ xfs_bmbt_to_bmdr( ASSERT(rblock->bb_level != 0); dblock->bb_level = rblock->bb_level; dblock->bb_numrecs = rblock->bb_numrecs; + + /* Validate record count against destination fork capacity */ + nrecs = be16_to_cpu(rblock->bb_numrecs); dmxr = xfs_bmdr_maxrecs(dblocklen, 0); + if (nrecs > dmxr) + return; + fkp = xfs_bmbt_key_addr(mp, rblock, 1); tkp = xfs_bmdr_key_addr(dblock, 1); fpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen); tpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr); - dmxr = be16_to_cpu(dblock->bb_numrecs); - memcpy(tkp, fkp, sizeof(*fkp) * dmxr); - memcpy(tpp, fpp, sizeof(*fpp) * dmxr); + memcpy(tkp, fkp, sizeof(*fkp) * nrecs); + memcpy(tpp, fpp, sizeof(*fpp) * nrecs); } STATIC struct xfs_btree_cur * -- 2.25.1