diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-03-23 10:06:56 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-03-23 18:05:08 -0700 |
commit | 6a96c5650568a2218712d43ec16f3f82296a6c53 (patch) | |
tree | f3f2067eac84a9daca478fc03eb2e285c97ef2e3 /fs | |
parent | 8bb82bc12a9e75dd47047d9a2e53135cc5e5787b (diff) |
xfs: don't accept inode buffers with suspicious unlinked chains
When we're verifying inode buffers, sanity-check the unlinked pointer.
We don't want to run the risk of trying to purge something that's
obviously broken.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index cdd4c1d58e80..f0cfcd79ac39 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -93,20 +93,26 @@ xfs_inode_buf_verify( bool readahead) { struct xfs_mount *mp = bp->b_target->bt_mount; + xfs_agnumber_t agno; int i; int ni; /* * Validate the magic number and version of every inode in the buffer */ + agno = xfs_daddr_to_agno(mp, XFS_BUF_ADDR(bp)); ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock; for (i = 0; i < ni; i++) { int di_ok; xfs_dinode_t *dip; + xfs_agino_t unlinked_ino; dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog)); + unlinked_ino = be32_to_cpu(dip->di_next_unlinked); di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) && - xfs_dinode_good_version(mp, dip->di_version); + xfs_dinode_good_version(mp, dip->di_version) && + (unlinked_ino == NULLAGINO || + xfs_verify_agino(mp, agno, unlinked_ino)); if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP))) { if (readahead) { @@ -124,9 +130,9 @@ xfs_inode_buf_verify( xfs_buf_verifier_error(bp, -EFSCORRUPTED, __func__, dip, sizeof(*dip), NULL); + return; } } - xfs_inobp_check(mp, bp); } |