Skip to content

Commit

Permalink
xfs: verify extent size hint is valid in inode verifier
Browse files Browse the repository at this point in the history
There are rules for vald extent size hints. We enforce them when
applications set them, but fuzzers violate those rules and that
screws us over.

This results in alignment assertion failures when setting up
allocations such as this in direct IO:

XFS: Assertion failed: ap->length, file: fs/xfs/libxfs/xfs_bmap.c, line: 3432
....
Call Trace:
 xfs_bmap_btalloc+0x415/0x910
 xfs_bmapi_write+0x71c/0x12e0
 xfs_iomap_write_direct+0x2a9/0x420
 xfs_file_iomap_begin+0x4dc/0xa70
 iomap_apply+0x43/0x100
 iomap_file_buffered_write+0x62/0x90
 xfs_file_buffered_aio_write+0xba/0x300
 __vfs_write+0xd5/0x150
 vfs_write+0xb6/0x180
 ksys_write+0x45/0xa0
 do_syscall_64+0x5a/0x180
 entry_SYSCALL_64_after_hwframe+0x49/0xbe

And from xfs_db:

core.extsize = 10380288

Which is not an integer multiple of the block size, and so violates
Rule #7 for setting extent size hints. Validate extent size hint
rules in the inode verifier to catch this.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
  • Loading branch information
Dave Chinner authored and djwong committed Jun 6, 2018
1 parent fa4ca9c commit 7d71a67
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion fs/xfs/libxfs/xfs_inode_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ xfs_dinode_verify(
xfs_ino_t ino,
struct xfs_dinode *dip)
{
xfs_failaddr_t fa;
uint16_t mode;
uint16_t flags;
uint64_t flags2;
Expand Down Expand Up @@ -513,6 +514,12 @@ xfs_dinode_verify(
return __this_address;
}

/* extent size hint validation */
fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize),
mode, flags);
if (fa)
return fa;

/* only version 3 or greater inodes are extensively verified here */
if (dip->di_version < 3)
return NULL;
Expand All @@ -521,7 +528,7 @@ xfs_dinode_verify(

/* don't allow reflink/cowextsize if we don't have reflink */
if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) &&
!xfs_sb_version_hasreflink(&mp->m_sb))
!xfs_sb_version_hasreflink(&mp->m_sb))
return __this_address;

/* only regular files get reflink */
Expand Down

0 comments on commit 7d71a67

Please sign in to comment.