xfs: check for dinode realtime flag corruption

Ramon tested XFS with a modified version of fsfuzzer and hit a NULL
pointer dereference in __xfs_get_blocks due to the RT device target
pointer being NULL.

To fix this reject inode with the realtime bit set on a a filesystem
without an RT subvolume during inode read.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Eric Sandeen <sandeen@sandeen.net>
Reviewed-by: Felix Blyakher <felixb@sgi.com>
Reported-by: Ramon de Carvalho Valle <ramon@risesecurity.org>
Tested-by: Ramon de Carvalho Valle <ramon@risesecurity.org>
Signed-off-by: Felix Blyakher <felixb@sgi.com>

authored by Christoph Hellwig and committed by Felix Blyakher b89d4208 e0c222c4

+10
+10
fs/xfs/xfs_inode.c
··· 343 return XFS_ERROR(EFSCORRUPTED); 344 } 345 346 switch (ip->i_d.di_mode & S_IFMT) { 347 case S_IFIFO: 348 case S_IFCHR:
··· 343 return XFS_ERROR(EFSCORRUPTED); 344 } 345 346 + if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && 347 + !ip->i_mount->m_rtdev_targp)) { 348 + xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, 349 + "corrupt dinode %Lu, has realtime flag set.", 350 + ip->i_ino); 351 + XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", 352 + XFS_ERRLEVEL_LOW, ip->i_mount, dip); 353 + return XFS_ERROR(EFSCORRUPTED); 354 + } 355 + 356 switch (ip->i_d.di_mode & S_IFMT) { 357 case S_IFIFO: 358 case S_IFCHR: