mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
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:
@@ -6227,7 +6227,7 @@ xfs_bmap_validate_extent(
|
|||||||
{
|
{
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
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;
|
return __this_address;
|
||||||
|
|
||||||
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
|
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
|
||||||
|
@@ -258,3 +258,28 @@ xfs_verify_dablk(
|
|||||||
|
|
||||||
return dabno <= max_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);
|
bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
|
||||||
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
|
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
|
||||||
unsigned long long *max);
|
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__ */
|
#endif /* __XFS_TYPES_H__ */
|
||||||
|
@@ -329,6 +329,10 @@ xchk_bmap_iextent(
|
|||||||
xchk_fblock_set_corrupt(info->sc, info->whichfork,
|
xchk_fblock_set_corrupt(info->sc, info->whichfork,
|
||||||
irec->br_startoff);
|
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);
|
xchk_bmap_dirattr_extent(ip, info, irec);
|
||||||
|
|
||||||
/* There should never be a "hole" extent in either extent list. */
|
/* 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))
|
if (!xfs_verify_ino(mp, bmap->me_owner))
|
||||||
return false;
|
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 false;
|
||||||
|
|
||||||
return xfs_verify_fsbext(mp, bmap->me_startblock, bmap->me_len);
|
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.
|
* the page cache can't scale that far.
|
||||||
*/
|
*/
|
||||||
first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
|
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);
|
WARN_ON_ONCE(first_unmap_block > XFS_MAX_FILEOFF);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -490,7 +490,7 @@ xfs_rui_validate_map(
|
|||||||
!xfs_verify_ino(mp, rmap->me_owner))
|
!xfs_verify_ino(mp, rmap->me_owner))
|
||||||
return false;
|
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 false;
|
||||||
|
|
||||||
return xfs_verify_fsbext(mp, rmap->me_startblock, rmap->me_len);
|
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
|
* Avoid integer overflow by comparing the maximum bmbt offset to the
|
||||||
* maximum pagecache offset in units of fs blocks.
|
* 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,
|
xfs_warn(mp,
|
||||||
"MAX_LFS_FILESIZE block offset (%llu) exceeds extent map maximum (%llu)!",
|
"MAX_LFS_FILESIZE block offset (%llu) exceeds extent map maximum (%llu)!",
|
||||||
XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE),
|
XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE),
|
||||||
|
Reference in New Issue
Block a user