]> git.baikalelectronics.ru Git - kernel.git/commitdiff
xfs: check owner of dir3 data blocks
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 26 Oct 2022 06:28:24 +0000 (11:58 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 29 Oct 2022 08:20:33 +0000 (10:20 +0200)
commit d707ee7a82bbe0246dc06cc64f337ef07d06081e upstream.

[Slightly edit xfs_dir3_data_read() to work with existing mapped_bno argument instead
of flag values introduced in later kernels]

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>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/libxfs/xfs_dir2_data.c

index 2c79be4c3153855d5dc3425bc590c135fe7e4786..2d92bcd8c80103bcf37d3e39beef2e746f3034cd 100644 (file)
@@ -348,6 +348,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(
@@ -357,12 +373,24 @@ xfs_dir3_data_read(
        xfs_daddr_t             mapped_bno,
        struct xfs_buf          **bpp)
 {
+       xfs_failaddr_t          fa;
        int                     err;
 
        err = xfs_da_read_buf(tp, dp, bno, mapped_bno, 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;
 }