xfs: verify extent size hint is valid in inode verifier
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>
This commit is contained in:
parent
fa4ca9c557
commit
7d71a671a2
|
@ -397,6 +397,7 @@ xfs_dinode_verify(
|
||||||
xfs_ino_t ino,
|
xfs_ino_t ino,
|
||||||
struct xfs_dinode *dip)
|
struct xfs_dinode *dip)
|
||||||
{
|
{
|
||||||
|
xfs_failaddr_t fa;
|
||||||
uint16_t mode;
|
uint16_t mode;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint64_t flags2;
|
uint64_t flags2;
|
||||||
|
@ -513,6 +514,12 @@ xfs_dinode_verify(
|
||||||
return __this_address;
|
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 */
|
/* only version 3 or greater inodes are extensively verified here */
|
||||||
if (dip->di_version < 3)
|
if (dip->di_version < 3)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue