[PATCH] xfs: fix heap buffer overflow in xfs_bmbt_to_bmdr
Hongling Zeng <[email protected]> Thu, 30 Jul 2026 16:34:04 +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]> --- fs/xfs/libxfs/xfs_bmap_btree.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 758a4b1ccf5b..3b606bd8aec9 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,12 +168,17 @@ 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); + tpp = xfs_bmdr_ptr_addr(dblock, 1, nrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); } -- 2.25.1