xfs: sanity check attr fork size
Recently we have quite a few kerneloops reports about dereferencing a NULL if_data in the attribute fork. From looking over the code this can only happen if we pass a 0 size argument to xfs_iformat_local. This implies some sort of corruption and in fact the only mailinglist report about this from earlier this year was after a powerfail presumably on a system with write cache and without barriers. Add a quick sanity check for the attr fork size in xfs_iformat to catch these early and without an oops. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
49739140e5
commit
b828d8c338
|
@ -424,6 +424,19 @@ xfs_iformat(
|
||||||
case XFS_DINODE_FMT_LOCAL:
|
case XFS_DINODE_FMT_LOCAL:
|
||||||
atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
|
atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
|
||||||
size = be16_to_cpu(atp->hdr.totsize);
|
size = be16_to_cpu(atp->hdr.totsize);
|
||||||
|
|
||||||
|
if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) {
|
||||||
|
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
|
||||||
|
"corrupt inode %Lu "
|
||||||
|
"(bad attr fork size %Ld).",
|
||||||
|
(unsigned long long) ip->i_ino,
|
||||||
|
(long long) size);
|
||||||
|
XFS_CORRUPTION_ERROR("xfs_iformat(8)",
|
||||||
|
XFS_ERRLEVEL_LOW,
|
||||||
|
ip->i_mount, dip);
|
||||||
|
return XFS_ERROR(EFSCORRUPTED);
|
||||||
|
}
|
||||||
|
|
||||||
error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
|
error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
|
||||||
break;
|
break;
|
||||||
case XFS_DINODE_FMT_EXTENTS:
|
case XFS_DINODE_FMT_EXTENTS:
|
||||||
|
|
Loading…
Reference in New Issue