xfs_repair: fix verify_ag_bno() overflow
PATCH 1/1 xfs_repair: fix verify_ag_bno() overflow
The last test in verify_ag_bno() may overflow:
return (agbno >= (sbp->sb_dblocks -
((sbp->sb_agcount - 1) * sbp->sb_agblocks)));
because sb_agcount & sb_agblocks are 32-bit integers; this may then miss corrupt agbnos for the last ag, which can in turn lead to out of bounds memory accesses later, for example when the block nr is used to offset in set_agbno_state():
addr = ba_bmap[(agno)] + (ag_blockno)/XR_BB_NUM;
Also make the first test simpler; agbno > sb_agblocks is -always- bad, regardless of the agno. This may even speed it up a tiny bit.
---
repair/dinode.c +7 -4
@@ -315,11 +315,14 @@ verify_ag_bno(xfs_sb_t *sbp, xfs_agnumber_t agno, xfs_agblock_t agbno) { -if (agno < (sbp->sb_agcount -1 )) -return (agbno >= sbp->sb_agblocks); -if (agno == (sbp->sb_agcount -1 )) +/* in all cases bno >= agblocks is bad */ +if (agbno >= sbp->sb_agblocks) +return 1 ; +/* last ag may be smaller */ +if (agno == (sbp->sb_agcount -1 ))return (agbno >= (sbp->sb_dblocks - - ((sbp->sb_agcount -1 ) * sbp->sb_agblocks))); + ((xfs_drfsbno_t)(sbp->sb_agcount -1 ) * + sbp->sb_agblocks)));return 1 ; }
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Argh self-nak on that one, stupid thinko; it always returns 1 for a non-last AG :/ Just add the cast and don't get fancy!
V2 below:
-------
The last test in verify_ag_bno() may overflow:
return (agbno >= (sbp->sb_dblocks -
((sbp->sb_agcount - 1) * sbp->sb_agblocks)));
because sb_agcount & sb_agblocks are 32-bit integers; this may then miss corrupt agbnos for the last ag, which can in turn lead to out of bounds memory accesses later, for example when the block nr is used to offset in set_agbno_state():
addr = ba_bmap[(agno)] + (ag_blockno)/XR_BB_NUM;
---
repair/dinode.c +2 -1
@@ -319,7 +319,8 @@ verify_ag_bno(xfs_sb_t *sbp,return (agbno >= sbp->sb_agblocks);if (agno == (sbp->sb_agcount -1 ))return (agbno >= (sbp->sb_dblocks - - ((sbp->sb_agcount -1 ) * sbp->sb_agblocks))); + ((xfs_drfsbno_t)(sbp->sb_agcount -1 ) * + sbp->sb_agblocks)));return 1 ; }
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v3 1/1 xfs_repair: fix agcount*agblocks overflows
(V3: found another spot with this problem)
The last test in verify_ag_bno() may overflow:
return (agbno >= (sbp->sb_dblocks -
((sbp->sb_agcount - 1) * sbp->sb_agblocks)));
because sb_agcount & sb_agblocks are 32-bit integers; this may then miss corrupt agbnos for the last ag, which can in turn lead to out of bounds memory accesses later, for example when the block nr is used to offset in set_agbno_state():
addr = ba_bmap[(agno)] + (ag_blockno)/XR_BB_NUM;
Similar problems in mk_incore_fstree
---
repair/dinode.c +2 -1
@@ -319,7 +319,8 @@ verify_ag_bno(xfs_sb_t *sbp,return (agbno >= sbp->sb_agblocks);if (agno == (sbp->sb_agcount -1 ))return (agbno >= (sbp->sb_dblocks - - ((sbp->sb_agcount -1 ) * sbp->sb_agblocks))); + ((xfs_drfsbno_t)(sbp->sb_agcount -1 ) * + sbp->sb_agblocks)));return 1 ; }
repair/phase5.c +2 -1
@@ -113,7 +113,8 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) ag_end = mp->m_sb.sb_agblocks; else ag_end = mp->m_sb.sb_dblocks - - mp->m_sb.sb_agblocks * (mp->m_sb.sb_agcount -1 ); + (xfs_drfsbno_t )mp->m_sb.sb_agblocks * + (mp->m_sb.sb_agcount -1 );/* * ok, now find the number of extents, keep track of the
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH V3] xfs_repair: fix agcount*agblocks overflows
Quoted 12 lines · Eric Sandeen
(V3: found another spot with this problem)
The last test in
verify_ag_bno()may overflow:return (agbno >= (
sbp->sb_dblocks-((sbp->sb_agcount - 1) * sbp->sb_agblocks)));because
sb_agcount&sb_agblocksare 32-bit integers; this may then miss corrupt agbnos for the last ag, which can in turn lead to out of bounds memory accesses later, for example when the block nr is used to offset inset_agbno_state():
Quoted 6 lines
addr = ba_bmap[(agno)] + (ag_blockno)/XR_BB_NUM;Similar problems in
mk_incore_fstreeReported-by Jesse Stroik <[email protected]>Signed-off-by Eric Sandeen <[email protected]>
Quoted 33 lines
---
repair/dinode.c +2
-1@@ -319,7 +319,8 @@ verify_ag_bno(xfs_sb_t *sbp,return (agbno >= sbp->sb_agblocks);if (agno == (sbp->sb_agcount -1 ))return (agbno >= (sbp->sb_dblocks - - ((sbp->sb_agcount -1 ) * sbp->sb_agblocks))); + ((xfs_drfsbno_t)(sbp->sb_agcount -1 ) * + sbp->sb_agblocks)));return 1 ; }repair/phase5.c +2
-1@@ -113,7 +113,8 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) ag_end = mp->m_sb.sb_agblocks; else ag_end = mp->m_sb.sb_dblocks - - mp->m_sb.sb_agblocks * (mp->m_sb.sb_agcount -1 ); + (xfs_drfsbno_t )mp->m_sb.sb_agblocks * + (mp->m_sb.sb_agcount -1 );/* * ok, now find the number of extents, keep track of the
Quoted 4 lines
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs