Commit 34c2c4f6 authored by Eric Anholt's avatar Eric Anholt

drm/v3d: Fix a use-after-free race accessing the scheduler's fences.

Once we push the job, the scheduler could run it and free it.  So, if
we want to reference their fences, we need to grab them before then.
I haven't seen this happen in many days of conformance test runtime,
but let's still close the race.
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
Fixes: 57692c94 ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
Link: https://patchwork.freedesktop.org/patch/254119/Reviewed-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
parent 73230015
...@@ -198,6 +198,11 @@ struct v3d_exec_info { ...@@ -198,6 +198,11 @@ struct v3d_exec_info {
*/ */
struct dma_fence *bin_done_fence; struct dma_fence *bin_done_fence;
/* Fence for when the scheduler considers the render to be
* done, for when the BOs reservations should be complete.
*/
struct dma_fence *render_done_fence;
struct kref refcount; struct kref refcount;
/* This is the array of BOs that were looked up at the start of exec. */ /* This is the array of BOs that were looked up at the start of exec. */
......
...@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d) ...@@ -209,7 +209,7 @@ v3d_flush_caches(struct v3d_dev *v3d)
static void static void
v3d_attach_object_fences(struct v3d_exec_info *exec) v3d_attach_object_fences(struct v3d_exec_info *exec)
{ {
struct dma_fence *out_fence = &exec->render.base.s_fence->finished; struct dma_fence *out_fence = exec->render_done_fence;
struct v3d_bo *bo; struct v3d_bo *bo;
int i; int i;
...@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref) ...@@ -409,6 +409,7 @@ v3d_exec_cleanup(struct kref *ref)
dma_fence_put(exec->render.done_fence); dma_fence_put(exec->render.done_fence);
dma_fence_put(exec->bin_done_fence); dma_fence_put(exec->bin_done_fence);
dma_fence_put(exec->render_done_fence);
for (i = 0; i < exec->bo_count; i++) for (i = 0; i < exec->bo_count; i++)
drm_gem_object_put_unlocked(&exec->bo[i]->base); drm_gem_object_put_unlocked(&exec->bo[i]->base);
...@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, ...@@ -572,6 +573,9 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
if (ret) if (ret)
goto fail_unreserve; goto fail_unreserve;
exec->render_done_fence =
dma_fence_get(&exec->render.base.s_fence->finished);
kref_get(&exec->refcount); /* put by scheduler job completion */ kref_get(&exec->refcount); /* put by scheduler job completion */
drm_sched_entity_push_job(&exec->render.base, drm_sched_entity_push_job(&exec->render.base,
&v3d_priv->sched_entity[V3D_RENDER]); &v3d_priv->sched_entity[V3D_RENDER]);
...@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, ...@@ -585,7 +589,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
sync_out = drm_syncobj_find(file_priv, args->out_sync); sync_out = drm_syncobj_find(file_priv, args->out_sync);
if (sync_out) { if (sync_out) {
drm_syncobj_replace_fence(sync_out, 0, drm_syncobj_replace_fence(sync_out, 0,
&exec->render.base.s_fence->finished); exec->render_done_fence);
drm_syncobj_put(sync_out); drm_syncobj_put(sync_out);
} }
......
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