Commit a37eef63 authored by Daniel Vetter's avatar Daniel Vetter

drm/syncobj: Fix use-after-free

While reviewing Christian's annotation patch I noticed that we have a
user-after-free for the WAIT_FOR_SUBMIT case: We drop the syncobj
reference before we've completed the waiting.

Of course usually there's nothing bad happening here since userspace
keeps the reference, but we can't rely on userspace to play nice here!
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Fixes: bc9c80fe ("drm/syncobj: use the timeline point in drm_syncobj_find_fence v4")
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v5.2+
Link: https://patchwork.freedesktop.org/patch/msgid/20210119130318.615145-1-daniel.vetter@ffwll.ch
parent abbc4d6e
...@@ -388,19 +388,18 @@ int drm_syncobj_find_fence(struct drm_file *file_private, ...@@ -388,19 +388,18 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
return -ENOENT; return -ENOENT;
*fence = drm_syncobj_fence_get(syncobj); *fence = drm_syncobj_fence_get(syncobj);
drm_syncobj_put(syncobj);
if (*fence) { if (*fence) {
ret = dma_fence_chain_find_seqno(fence, point); ret = dma_fence_chain_find_seqno(fence, point);
if (!ret) if (!ret)
return 0; goto out;
dma_fence_put(*fence); dma_fence_put(*fence);
} else { } else {
ret = -EINVAL; ret = -EINVAL;
} }
if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)) if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
return ret; goto out;
memset(&wait, 0, sizeof(wait)); memset(&wait, 0, sizeof(wait));
wait.task = current; wait.task = current;
...@@ -432,6 +431,9 @@ int drm_syncobj_find_fence(struct drm_file *file_private, ...@@ -432,6 +431,9 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
if (wait.node.next) if (wait.node.next)
drm_syncobj_remove_wait(syncobj, &wait); drm_syncobj_remove_wait(syncobj, &wait);
out:
drm_syncobj_put(syncobj);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_syncobj_find_fence); EXPORT_SYMBOL(drm_syncobj_find_fence);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment