Skip to content

Commit

Permalink
drm/panfrost: Job should reference MMU not file_priv
Browse files Browse the repository at this point in the history
For a while now it's been allowed for a MMU context to outlive it's
corresponding panfrost_priv, however the job structure still references
panfrost_priv to get hold of the MMU context. If panfrost_priv has been
freed this is a use-after-free which I've been able to trigger resulting
in a splat.

To fix this, drop the reference to panfrost_priv in the job structure
and add a direct reference to the MMU structure which is what's actually
needed.

Fixes: 7fdc48c ("drm/panfrost: Make sure MMU context lifetime is not bound to panfrost_priv")
Signed-off-by: Steven Price <[email protected]>
Acked-by: Alyssa Rosenzweig <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
Steven Price committed May 25, 2022
1 parent edbc796 commit 6e516fa
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 6 deletions.
5 changes: 3 additions & 2 deletions drivers/gpu/drm/panfrost/panfrost_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct panfrost_device *pfdev = dev->dev_private;
struct panfrost_file_priv *file_priv = file->driver_priv;
struct drm_panfrost_submit *args = data;
struct drm_syncobj *sync_out = NULL;
struct panfrost_job *job;
Expand Down Expand Up @@ -262,12 +263,12 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data,
job->jc = args->jc;
job->requirements = args->requirements;
job->flush_id = panfrost_gpu_get_latest_flush_id(pfdev);
job->file_priv = file->driver_priv;
job->mmu = file_priv->mmu;

slot = panfrost_job_get_slot(job);

ret = drm_sched_job_init(&job->base,
&job->file_priv->sched_entity[slot],
&file_priv->sched_entity[slot],
NULL);
if (ret)
goto out_put_job;
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/panfrost/panfrost_job.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
return;
}

cfg = panfrost_mmu_as_get(pfdev, job->file_priv->mmu);
cfg = panfrost_mmu_as_get(pfdev, job->mmu);

job_write(pfdev, JS_HEAD_NEXT_LO(js), lower_32_bits(jc_head));
job_write(pfdev, JS_HEAD_NEXT_HI(js), upper_32_bits(jc_head));
Expand Down Expand Up @@ -431,7 +431,7 @@ static void panfrost_job_handle_err(struct panfrost_device *pfdev,
job->jc = 0;
}

panfrost_mmu_as_put(pfdev, job->file_priv->mmu);
panfrost_mmu_as_put(pfdev, job->mmu);
panfrost_devfreq_record_idle(&pfdev->pfdevfreq);

if (signal_fence)
Expand All @@ -452,7 +452,7 @@ static void panfrost_job_handle_done(struct panfrost_device *pfdev,
* happen when we receive the DONE interrupt while doing a GPU reset).
*/
job->jc = 0;
panfrost_mmu_as_put(pfdev, job->file_priv->mmu);
panfrost_mmu_as_put(pfdev, job->mmu);
panfrost_devfreq_record_idle(&pfdev->pfdevfreq);

dma_fence_signal_locked(job->done_fence);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/panfrost/panfrost_job.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct panfrost_job {
struct kref refcount;

struct panfrost_device *pfdev;
struct panfrost_file_priv *file_priv;
struct panfrost_mmu *mmu;

/* Fence to be signaled by IRQ handler when the job is complete. */
struct dma_fence *done_fence;
Expand Down

0 comments on commit 6e516fa

Please sign in to comment.