lkml.org 
[lkml]   [2017]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 096/109] dma-buf/sw_sync: clean up list before signaling the fence
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Gustavo Padovan <gustavo.padovan@collabora.com>

    commit 3792b7c1a70815fe4e954221c096f9278638fd21 upstream.

    If userspace already dropped its own reference by closing the sw_sync
    fence fd we might end up in a deadlock where
    dma_fence_is_signaled_locked() will trigger the release of the fence and
    thus try to hold the lock to remove the fence from the list.

    dma_fence_is_signaled_locked() tries to release/free the fence and hold
    the lock in the process.

    We fix that by changing the order operation and clean up the list and
    rb-tree first.

    v2: Drop fence get/put dance and manipulate the list first (Chris Wilson)

    Cc: Chris Wilson <chris@chris-wilson.co.uk>
    Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
    Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
    Link: https://patchwork.freedesktop.org/patch/msgid/20170729152217.8362-2-gustavo@padovan.org
    [s/dma_fence/fence/g - gregkh]
    Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/dma-buf/sw_sync.c | 12 +++++++++++-
    1 file changed, 11 insertions(+), 1 deletion(-)

    --- a/drivers/dma-buf/sw_sync.c
    +++ b/drivers/dma-buf/sw_sync.c
    @@ -213,11 +213,21 @@ static void sync_timeline_signal(struct
    obj->value += inc;

    list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
    - if (!fence_is_signaled_locked(&pt->base))
    + if (!timeline_fence_signaled(&pt->base))
    break;

    list_del_init(&pt->link);
    rb_erase(&pt->node, &obj->pt_tree);
    +
    + /*
    + * A signal callback may release the last reference to this
    + * fence, causing it to be freed. That operation has to be
    + * last to avoid a use after free inside this loop, and must
    + * be after we remove the fence from the timeline in order to
    + * prevent deadlocking on timeline->lock inside
    + * timeline_fence_release().
    + */
    + fence_signal_locked(&pt->base);
    }

    spin_unlock_irq(&obj->lock);

    \
     
     \ /
      Last update: 2017-12-07 14:04    [W:4.335 / U:0.248 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site