lkml.org 
[lkml]   [2020]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.4 052/330] xfs: fix attr leaf header freemap.size underflow
    Date
    From: Brian Foster <bfoster@redhat.com>

    [ Upstream commit 2a2b5932db67586bacc560cc065d62faece5b996 ]

    The leaf format xattr addition helper xfs_attr3_leaf_add_work()
    adjusts the block freemap in a couple places. The first update drops
    the size of the freemap that the caller had already selected to
    place the xattr name/value data. Before the function returns, it
    also checks whether the entries array has encroached on a freemap
    range by virtue of the new entry addition. This is necessary because
    the entries array grows from the start of the block (but end of the
    block header) towards the end of the block while the name/value data
    grows from the end of the block in the opposite direction. If the
    associated freemap is already empty, however, size is zero and the
    subtraction underflows the field and causes corruption.

    This is reproduced rarely by generic/070. The observed behavior is
    that a smaller sized freemap is aligned to the end of the entries
    list, several subsequent xattr additions land in larger freemaps and
    the entries list expands into the smaller freemap until it is fully
    consumed and then underflows. Note that it is not otherwise a
    corruption for the entries array to consume an empty freemap because
    the nameval list (i.e. the firstused pointer in the xattr header)
    starts beyond the end of the corrupted freemap.

    Update the freemap size modification to account for the fact that
    the freemap entry can be empty and thus stale.

    Signed-off-by: Brian Foster <bfoster@redhat.com>
    Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/xfs/libxfs/xfs_attr_leaf.c | 4 +++-
    1 file changed, 3 insertions(+), 1 deletion(-)

    diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
    index b133209f3aa6a..f1535549d1ced 100644
    --- a/fs/xfs/libxfs/xfs_attr_leaf.c
    +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
    @@ -1451,7 +1451,9 @@ xfs_attr3_leaf_add_work(
    for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
    if (ichdr->freemap[i].base == tmp) {
    ichdr->freemap[i].base += sizeof(xfs_attr_leaf_entry_t);
    - ichdr->freemap[i].size -= sizeof(xfs_attr_leaf_entry_t);
    + ichdr->freemap[i].size -=
    + min_t(uint16_t, ichdr->freemap[i].size,
    + sizeof(xfs_attr_leaf_entry_t));
    }
    }
    ichdr->usedbytes += xfs_attr_leaf_entsize(leaf, args->index);
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-09-18 05:14    [W:2.107 / U:0.140 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site