lkml.org 
[lkml]   [2020]   [Nov]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 098/151] xfs: fix rmap key and record comparison functions
    Date
    From: Darrick J. Wong <darrick.wong@oracle.com>

    [ Upstream commit 6ff646b2ceb0eec916101877f38da0b73e3a5b7f ]

    Keys for extent interval records in the reverse mapping btree are
    supposed to be computed as follows:

    (physical block, owner, fork, is_btree, is_unwritten, offset)

    This provides users the ability to look up a reverse mapping from a bmbt
    record -- start with the physical block; then if there are multiple
    records for the same block, move on to the owner; then the inode fork
    type; and so on to the file offset.

    However, the key comparison functions incorrectly remove the
    fork/btree/unwritten information that's encoded in the on-disk offset.
    This means that lookup comparisons are only done with:

    (physical block, owner, offset)

    This means that queries can return incorrect results. On consistent
    filesystems this hasn't been an issue because blocks are never shared
    between forks or with bmbt blocks; and are never unwritten. However,
    this bug means that online repair cannot always detect corruption in the
    key information in internal rmapbt nodes.

    Found by fuzzing keys[1].attrfork = ones on xfs/371.

    Fixes: 4b8ed67794fe ("xfs: add rmap btree operations")
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Reviewed-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/xfs/libxfs/xfs_rmap_btree.c | 16 ++++++++--------
    1 file changed, 8 insertions(+), 8 deletions(-)

    diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
    index fc78efa52c94e..3780609c7860c 100644
    --- a/fs/xfs/libxfs/xfs_rmap_btree.c
    +++ b/fs/xfs/libxfs/xfs_rmap_btree.c
    @@ -243,8 +243,8 @@ xfs_rmapbt_key_diff(
    else if (y > x)
    return -1;

    - x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset));
    - y = rec->rm_offset;
    + x = be64_to_cpu(kp->rm_offset);
    + y = xfs_rmap_irec_offset_pack(rec);
    if (x > y)
    return 1;
    else if (y > x)
    @@ -275,8 +275,8 @@ xfs_rmapbt_diff_two_keys(
    else if (y > x)
    return -1;

    - x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset));
    - y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset));
    + x = be64_to_cpu(kp1->rm_offset);
    + y = be64_to_cpu(kp2->rm_offset);
    if (x > y)
    return 1;
    else if (y > x)
    @@ -390,8 +390,8 @@ xfs_rmapbt_keys_inorder(
    return 1;
    else if (a > b)
    return 0;
    - a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset));
    - b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset));
    + a = be64_to_cpu(k1->rmap.rm_offset);
    + b = be64_to_cpu(k2->rmap.rm_offset);
    if (a <= b)
    return 1;
    return 0;
    @@ -420,8 +420,8 @@ xfs_rmapbt_recs_inorder(
    return 1;
    else if (a > b)
    return 0;
    - a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset));
    - b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset));
    + a = be64_to_cpu(r1->rmap.rm_offset);
    + b = be64_to_cpu(r2->rmap.rm_offset);
    if (a <= b)
    return 1;
    return 0;
    --
    2.27.0


    \
     
     \ /
      Last update: 2020-11-17 14:29    [W:4.028 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site