diff mbox series

[3/4] xfs: refactor file range validation

Message ID 160729626928.1608297.12355625902682243490.stgit@magnolia (mailing list archive)
State Accepted, archived
Headers show
Series xfs: refactor extent validation for 5.11 | expand

Commit Message

Darrick J. Wong Dec. 6, 2020, 11:11 p.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

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>
---
 fs/xfs/libxfs/xfs_bmap.c  |    2 +-
 fs/xfs/libxfs/xfs_types.c |   25 +++++++++++++++++++++++++
 fs/xfs/libxfs/xfs_types.h |    3 +++
 fs/xfs/scrub/bmap.c       |    4 ++++
 fs/xfs/xfs_bmap_item.c    |    2 +-
 fs/xfs/xfs_rmap_item.c    |    2 +-
 6 files changed, 35 insertions(+), 3 deletions(-)

Comments

Dave Chinner Dec. 6, 2020, 11:56 p.m. UTC | #1
On Sun, Dec 06, 2020 at 03:11:09PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> 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>
> ---
>  fs/xfs/libxfs/xfs_bmap.c  |    2 +-
>  fs/xfs/libxfs/xfs_types.c |   25 +++++++++++++++++++++++++
>  fs/xfs/libxfs/xfs_types.h |    3 +++
>  fs/xfs/scrub/bmap.c       |    4 ++++
>  fs/xfs/xfs_bmap_item.c    |    2 +-
>  fs/xfs/xfs_rmap_item.c    |    2 +-
>  6 files changed, 35 insertions(+), 3 deletions(-)

Looks fine.

Reviewed-by: Dave Chinner <dchinner@redhat.com>
Christoph Hellwig Dec. 7, 2020, 2:17 p.m. UTC | #2
> +/* 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;
> +}

I think an inline function would make sense here..

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>
Brian Foster Dec. 7, 2020, 5:46 p.m. UTC | #3
On Sun, Dec 06, 2020 at 03:11:09PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> 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>

>  fs/xfs/libxfs/xfs_bmap.c  |    2 +-
>  fs/xfs/libxfs/xfs_types.c |   25 +++++++++++++++++++++++++
>  fs/xfs/libxfs/xfs_types.h |    3 +++
>  fs/xfs/scrub/bmap.c       |    4 ++++
>  fs/xfs/xfs_bmap_item.c    |    2 +-
>  fs/xfs/xfs_rmap_item.c    |    2 +-
>  6 files changed, 35 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 7bcf498ef6b2..dcf56bcafb8f 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -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) {
> diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
> index 7b310eb296b7..b254fbeaaa50 100644
> --- a/fs/xfs/libxfs/xfs_types.c
> +++ b/fs/xfs/libxfs/xfs_types.c
> @@ -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);
> +}
> diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
> index 18e83ce46568..064bd6e8c922 100644
> --- a/fs/xfs/libxfs/xfs_types.h
> +++ b/fs/xfs/libxfs/xfs_types.h
> @@ -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__ */
> diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
> index cce8ac7d3973..bce4421acdb9 100644
> --- a/fs/xfs/scrub/bmap.c
> +++ b/fs/xfs/scrub/bmap.c
> @@ -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. */
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 5c9706760e68..9a2e54b7ccb9 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -449,7 +449,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);
> diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
> index 4fa875237422..49cebd68b672 100644
> --- a/fs/xfs/xfs_rmap_item.c
> +++ b/fs/xfs/xfs_rmap_item.c
> @@ -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);
>
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 7bcf498ef6b2..dcf56bcafb8f 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -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) {
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
index 7b310eb296b7..b254fbeaaa50 100644
--- a/fs/xfs/libxfs/xfs_types.c
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -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);
+}
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index 18e83ce46568..064bd6e8c922 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -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__ */
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index cce8ac7d3973..bce4421acdb9 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -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. */
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 5c9706760e68..9a2e54b7ccb9 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -449,7 +449,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);
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index 4fa875237422..49cebd68b672 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -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);