From 7161cd21b3ed3fa82aef1f13b2bcfae045208573 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sat, 9 May 2020 13:11:59 -0400 Subject: [PATCH] xfs_db: bounds-check access to the dbmap array Try to check the array boundaries of the dbmap array so that we don't just segfault. Found by fuzzing xfs/358 with recs[1].blockcount = ones. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Eric Sandeen --- db/check.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/db/check.c b/db/check.c index c9bafa8e3..6f0478771 100644 --- a/db/check.c +++ b/db/check.c @@ -1294,6 +1294,18 @@ check_blist( return 0; } +static inline bool +dbmap_boundscheck( + xfs_agnumber_t agno, + xfs_agblock_t agbno) +{ + if (agno >= mp->m_sb.sb_agcount) + return false; + if (agbno >= mp->m_sb.sb_agblocks) + return false; + return true; +} + static void check_dbmap( xfs_agnumber_t agno, @@ -1307,6 +1319,12 @@ check_dbmap( dbm_t d; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { + if (!dbmap_boundscheck(agno, agbno + i)) { + dbprintf(_("block %u/%u beyond end of expected area\n"), + agno, agbno + i); + error++; + break; + } d = (dbm_t)*p; if (ignore_reflink && (d == DBM_UNKNOWN || d == DBM_DATA || d == DBM_RLDATA)) @@ -1468,6 +1486,13 @@ check_range( return 1; } +static inline bool +rdbmap_boundscheck( + xfs_rfsblock_t bno) +{ + return bno < mp->m_sb.sb_agblocks; +} + static void check_rdbmap( xfs_rfsblock_t bno, @@ -1478,6 +1503,12 @@ check_rdbmap( char *p; for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { + if (!rdbmap_boundscheck(bno + i)) { + dbprintf(_("rtblock %llu beyond end of expected area\n"), + bno + i); + error++; + break; + } if ((dbm_t)*p != type) { if (!sflag || CHECK_BLIST(bno + i)) dbprintf(_("rtblock %llu expected type %s got " @@ -1599,6 +1630,12 @@ check_set_dbmap( check_dbmap(agno, agbno, len, type1, is_reflink(type2)); mayprint = verbose | blist_size; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { + if (!dbmap_boundscheck(agno, agbno + i)) { + dbprintf(_("block %u/%u beyond end of expected area\n"), + agno, agbno + i); + error++; + break; + } if (*p == DBM_RLDATA && type2 == DBM_DATA) ; /* do nothing */ else if (*p == DBM_DATA && type2 == DBM_DATA) @@ -1627,6 +1664,12 @@ check_set_rdbmap( check_rdbmap(bno, len, type1); mayprint = verbose | blist_size; for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { + if (!rdbmap_boundscheck(bno + i)) { + dbprintf(_("rtblock %llu beyond end of expected area\n"), + bno + i); + error++; + break; + } *p = (char)type2; if (mayprint && (verbose || CHECK_BLIST(bno + i))) dbprintf(_("setting rtblock %llu to %s\n"), -- 2.47.3