OSDN Git Service

xfs: check owner of dir3 data blocks
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 11 Mar 2020 17:37:56 +0000 (10:37 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 12 Mar 2020 14:58:12 +0000 (07:58 -0700)
Check the owner field of dir3 data block headers.  If it's corrupt,
release the buffer and return EFSCORRUPTED.  All callers handle this
properly.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_dir2_data.c

index b9eba82..375b3ed 100644 (file)
@@ -394,6 +394,22 @@ static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
        .verify_write = xfs_dir3_data_write_verify,
 };
 
+static xfs_failaddr_t
+xfs_dir3_data_header_check(
+       struct xfs_inode        *dp,
+       struct xfs_buf          *bp)
+{
+       struct xfs_mount        *mp = dp->i_mount;
+
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
+
+               if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino)
+                       return __this_address;
+       }
+
+       return NULL;
+}
 
 int
 xfs_dir3_data_read(
@@ -403,12 +419,24 @@ xfs_dir3_data_read(
        unsigned int            flags,
        struct xfs_buf          **bpp)
 {
+       xfs_failaddr_t          fa;
        int                     err;
 
        err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK,
                        &xfs_dir3_data_buf_ops);
-       if (!err && tp && *bpp)
-               xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
+       if (err || !*bpp)
+               return err;
+
+       /* Check things that we can't do in the verifier. */
+       fa = xfs_dir3_data_header_check(dp, *bpp);
+       if (fa) {
+               __xfs_buf_mark_corrupt(*bpp, fa);
+               xfs_trans_brelse(tp, *bpp);
+               *bpp = NULL;
+               return -EFSCORRUPTED;
+       }
+
+       xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
        return err;
 }