forked from Minki/linux
xfs: refactor file range validation
Refactor all the open-coded validation of file block ranges into a single helper, and teach the bmap scrubber to check the ranges. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
18695ad425
commit
33005fd0a5
@ -6227,7 +6227,7 @@ xfs_bmap_validate_extent(
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
|
||||
if (irec->br_startoff + irec->br_blockcount <= irec->br_startoff)
|
||||
if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
|
||||
return __this_address;
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
|
||||
|
@ -258,3 +258,28 @@ xfs_verify_dablk(
|
||||
|
||||
return dabno <= max_dablk;
|
||||
}
|
||||
|
||||
/* Check that a file block offset does not exceed the maximum. */
|
||||
bool
|
||||
xfs_verify_fileoff(
|
||||
struct xfs_mount *mp,
|
||||
xfs_fileoff_t off)
|
||||
{
|
||||
return off <= XFS_MAX_FILEOFF;
|
||||
}
|
||||
|
||||
/* Check that a range of file block offsets do not exceed the maximum. */
|
||||
bool
|
||||
xfs_verify_fileext(
|
||||
struct xfs_mount *mp,
|
||||
xfs_fileoff_t off,
|
||||
xfs_fileoff_t len)
|
||||
{
|
||||
if (off + len <= off)
|
||||
return false;
|
||||
|
||||
if (!xfs_verify_fileoff(mp, off))
|
||||
return false;
|
||||
|
||||
return xfs_verify_fileoff(mp, off + len - 1);
|
||||
}
|
||||
|
@ -203,5 +203,8 @@ bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
|
||||
bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
|
||||
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
|
||||
unsigned long long *max);
|
||||
bool xfs_verify_fileoff(struct xfs_mount *mp, xfs_fileoff_t off);
|
||||
bool xfs_verify_fileext(struct xfs_mount *mp, xfs_fileoff_t off,
|
||||
xfs_fileoff_t len);
|
||||
|
||||
#endif /* __XFS_TYPES_H__ */
|
||||
|
@ -329,6 +329,10 @@ xchk_bmap_iextent(
|
||||
xchk_fblock_set_corrupt(info->sc, info->whichfork,
|
||||
irec->br_startoff);
|
||||
|
||||
if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
|
||||
xchk_fblock_set_corrupt(info->sc, info->whichfork,
|
||||
irec->br_startoff);
|
||||
|
||||
xchk_bmap_dirattr_extent(ip, info, irec);
|
||||
|
||||
/* There should never be a "hole" extent in either extent list. */
|
||||
|
@ -445,7 +445,7 @@ xfs_bui_validate(
|
||||
if (!xfs_verify_ino(mp, bmap->me_owner))
|
||||
return false;
|
||||
|
||||
if (bmap->me_startoff + bmap->me_len <= bmap->me_startoff)
|
||||
if (!xfs_verify_fileext(mp, bmap->me_startoff, bmap->me_len))
|
||||
return false;
|
||||
|
||||
return xfs_verify_fsbext(mp, bmap->me_startblock, bmap->me_len);
|
||||
|
@ -1521,7 +1521,7 @@ xfs_itruncate_extents_flags(
|
||||
* the page cache can't scale that far.
|
||||
*/
|
||||
first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
|
||||
if (first_unmap_block >= XFS_MAX_FILEOFF) {
|
||||
if (!xfs_verify_fileoff(mp, first_unmap_block)) {
|
||||
WARN_ON_ONCE(first_unmap_block > XFS_MAX_FILEOFF);
|
||||
return 0;
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ xfs_rui_validate_map(
|
||||
!xfs_verify_ino(mp, rmap->me_owner))
|
||||
return false;
|
||||
|
||||
if (rmap->me_startoff + rmap->me_len <= rmap->me_startoff)
|
||||
if (!xfs_verify_fileext(mp, rmap->me_startoff, rmap->me_len))
|
||||
return false;
|
||||
|
||||
return xfs_verify_fsbext(mp, rmap->me_startblock, rmap->me_len);
|
||||
|
@ -1517,7 +1517,7 @@ xfs_fc_fill_super(
|
||||
* Avoid integer overflow by comparing the maximum bmbt offset to the
|
||||
* maximum pagecache offset in units of fs blocks.
|
||||
*/
|
||||
if (XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE) > XFS_MAX_FILEOFF) {
|
||||
if (!xfs_verify_fileoff(mp, XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE))) {
|
||||
xfs_warn(mp,
|
||||
"MAX_LFS_FILESIZE block offset (%llu) exceeds extent map maximum (%llu)!",
|
||||
XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE),
|
||||
|
Loading…
Reference in New Issue
Block a user