lkml.org 
[lkml]   [2017]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 021/250] Btrfs: fix tree search logic when replaying directory entry deletes
    Date
    From: Robbie Ko <robbieko@synology.com>

    commit 2a7bf53f577e49c43de4ffa7776056de26db65d9 upstream.

    If a log tree has a layout like the following:

    leaf N:
    ...
    item 240 key (282 DIR_LOG_ITEM 0) itemoff 8189 itemsize 8
    dir log end 1275809046
    leaf N + 1:
    item 0 key (282 DIR_LOG_ITEM 3936149215) itemoff 16275 itemsize 8
    dir log end 18446744073709551615
    ...

    When we pass the value 1275809046 + 1 as the parameter start_ret to the
    function tree-log.c:find_dir_range() (done by replay_dir_deletes()), we
    end up with path->slots[0] having the value 239 (points to the last item
    of leaf N, item 240). Because the dir log item in that position has an
    offset value smaller than *start_ret (1275809046 + 1) we need to move on
    to the next leaf, however the logic for that is wrong since it compares
    the current slot to the number of items in the leaf, which is smaller
    and therefore we don't lookup for the next leaf but instead we set the
    slot to point to an item that does not exist, at slot 240, and we later
    operate on that slot which has unexpected content or in the worst case
    can result in an invalid memory access (accessing beyond the last page
    of leaf N's extent buffer).

    So fix the logic that checks when we need to lookup at the next leaf
    by first incrementing the slot and only after to check if that slot
    is beyond the last item of the current leaf.

    Signed-off-by: Robbie Ko <robbieko@synology.com>
    Reviewed-by: Filipe Manana <fdmanana@suse.com>
    Fixes: e02119d5a7b4 (Btrfs: Add a write ahead tree log to optimize synchronous operations)
    Signed-off-by: Filipe Manana <fdmanana@suse.com>
    [Modified changelog for clarity and correctness]
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    ---
    fs/btrfs/tree-log.c | 3 +--
    1 file changed, 1 insertion(+), 2 deletions(-)

    diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
    index 7d3331c..681782d 100644
    --- a/fs/btrfs/tree-log.c
    +++ b/fs/btrfs/tree-log.c
    @@ -1691,12 +1691,11 @@ static noinline int find_dir_range(struct btrfs_root *root,
    next:
    /* check the next slot in the tree to see if it is a valid item */
    nritems = btrfs_header_nritems(path->nodes[0]);
    + path->slots[0]++;
    if (path->slots[0] >= nritems) {
    ret = btrfs_next_leaf(root, path);
    if (ret)
    goto out;
    - } else {
    - path->slots[0]++;
    }

    btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
    --
    2.8.0.rc2.1.gbe9624a
    \
     
     \ /
      Last update: 2017-06-12 01:17    [W:2.821 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site