diff mbox

[1/3] xfs: ubsan fixes

Message ID 151189079681.14861.10709810493861130558.stgit@magnolia (mailing list archive)
State Accepted
Headers show

Commit Message

Darrick J. Wong Nov. 28, 2017, 5:39 p.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

Fix some complaints from the UBSAN about signed integer addition overflows.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/xfs_aops.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Brian Foster Nov. 30, 2017, 1:47 p.m. UTC | #1
On Tue, Nov 28, 2017 at 09:39:56AM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Fix some complaints from the UBSAN about signed integer addition overflows.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

Seems Ok:

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_aops.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index a3eeaba..b0cccf8 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -399,7 +399,7 @@ xfs_map_blocks(
>  	       (ip->i_df.if_flags & XFS_IFEXTENTS));
>  	ASSERT(offset <= mp->m_super->s_maxbytes);
>  
> -	if (offset + count > mp->m_super->s_maxbytes)
> +	if ((xfs_ufsize_t)offset + count > mp->m_super->s_maxbytes)
>  		count = mp->m_super->s_maxbytes - offset;
>  	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
>  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
> @@ -1265,7 +1265,7 @@ xfs_map_trim_size(
>  	if (mapping_size > size)
>  		mapping_size = size;
>  	if (offset < i_size_read(inode) &&
> -	    offset + mapping_size >= i_size_read(inode)) {
> +	    (xfs_ufsize_t)offset + mapping_size >= i_size_read(inode)) {
>  		/* limit mapping to block that spans EOF */
>  		mapping_size = roundup_64(i_size_read(inode) - offset,
>  					  i_blocksize(inode));
> @@ -1312,7 +1312,7 @@ xfs_get_blocks(
>  	lockmode = xfs_ilock_data_map_shared(ip);
>  
>  	ASSERT(offset <= mp->m_super->s_maxbytes);
> -	if (offset + size > mp->m_super->s_maxbytes)
> +	if ((xfs_ufsize_t)offset + size > mp->m_super->s_maxbytes)
>  		size = mp->m_super->s_maxbytes - offset;
>  	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
>  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christoph Hellwig Dec. 14, 2017, 4:33 p.m. UTC | #2
On Tue, Nov 28, 2017 at 09:39:56AM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Fix some complaints from the UBSAN about signed integer addition overflows.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

I only noticed that now that it's in Linus' tree.  Need to find some
more time for the XFS list..

> -	if (offset + count > mp->m_super->s_maxbytes)
> +	if ((xfs_ufsize_t)offset + count > mp->m_super->s_maxbytes)
>  		count = mp->m_super->s_maxbytes - offset;

I don't think this fix is useful in any meaninfless way.  Yes,
signed overflow in C is undefined, and unsigned overflow is and this
will shut up UBSAN.  But it doesn't solve the problem at all.

Assuming we still need these checks and the VFS doesn't take care of
it already (I'd need to double check) we want to truncate at s_maxbytes,
and assuming s_maxbytes is close to ULLONG_MAX and count makes it
overflow this will give the wrong result, as it won't cap anything.

What we'd need instead would be something like:

	if (offset > mp->m_super->s_maxbytes - count)
		count = mp->m_super->s_maxbytes - offset;

as that does the right thing.
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index a3eeaba..b0cccf8 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -399,7 +399,7 @@  xfs_map_blocks(
 	       (ip->i_df.if_flags & XFS_IFEXTENTS));
 	ASSERT(offset <= mp->m_super->s_maxbytes);
 
-	if (offset + count > mp->m_super->s_maxbytes)
+	if ((xfs_ufsize_t)offset + count > mp->m_super->s_maxbytes)
 		count = mp->m_super->s_maxbytes - offset;
 	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
@@ -1265,7 +1265,7 @@  xfs_map_trim_size(
 	if (mapping_size > size)
 		mapping_size = size;
 	if (offset < i_size_read(inode) &&
-	    offset + mapping_size >= i_size_read(inode)) {
+	    (xfs_ufsize_t)offset + mapping_size >= i_size_read(inode)) {
 		/* limit mapping to block that spans EOF */
 		mapping_size = roundup_64(i_size_read(inode) - offset,
 					  i_blocksize(inode));
@@ -1312,7 +1312,7 @@  xfs_get_blocks(
 	lockmode = xfs_ilock_data_map_shared(ip);
 
 	ASSERT(offset <= mp->m_super->s_maxbytes);
-	if (offset + size > mp->m_super->s_maxbytes)
+	if ((xfs_ufsize_t)offset + size > mp->m_super->s_maxbytes)
 		size = mp->m_super->s_maxbytes - offset;
 	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);