diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_buf.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 30 | 
1 files changed, 30 insertions, 0 deletions
| diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 30d1d60f1d46..09d9c8cfa4a0 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -415,6 +415,31 @@ xfs_dinode_verify_fork(  	return NULL;  } +static xfs_failaddr_t +xfs_dinode_verify_forkoff( +	struct xfs_dinode	*dip, +	struct xfs_mount	*mp) +{ +	if (!XFS_DFORK_Q(dip)) +		return NULL; + +	switch (dip->di_format)  { +	case XFS_DINODE_FMT_DEV: +		if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3)) +			return __this_address; +		break; +	case XFS_DINODE_FMT_LOCAL:	/* fall through ... */ +	case XFS_DINODE_FMT_EXTENTS:    /* fall through ... */ +	case XFS_DINODE_FMT_BTREE: +		if (dip->di_forkoff >= (XFS_LITINO(mp, dip->di_version) >> 3)) +			return __this_address; +		break; +	default: +		return __this_address; +	} +	return NULL; +} +  xfs_failaddr_t  xfs_dinode_verify(  	struct xfs_mount	*mp, @@ -470,6 +495,11 @@ xfs_dinode_verify(  	if (mode && (flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)  		return __this_address; +	/* check for illegal values of forkoff */ +	fa = xfs_dinode_verify_forkoff(dip, mp); +	if (fa) +		return fa; +  	/* Do we have appropriate data fork formats for the mode? */  	switch (mode & S_IFMT) {  	case S_IFIFO: |