[SRU][J][PATCH 1/1] drm/panfrost: Job should reference MMU not file_priv
Cengiz Can
cengiz.can at canonical.com
Tue Sep 8 23:50:50 UTC 2026
From: Steven Price <steven.price at arm.com>
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: 7fdc48cc63a3 ("drm/panfrost: Make sure MMU context lifetime is not bound to panfrost_priv")
Signed-off-by: Steven Price <steven.price at arm.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220519152003.81081-1-steven.price@arm.com
(backported from commit 6e516faf04317db2c46cbec4e3b78b4653a5b109)
[bot_kybele: This tree calls drm_sched_job_init/entity lookup inside
panfrost_job_push() (job.c) via job->file_priv->sched_entity, not in the submit
ioctl; so instead of upstream's drv.c drm_sched_job_init block, I pass
file_priv into panfrost_job_push() (updating its decl in job.h and the drv.c
call) and take sched_entity from that param, keeping job free of file_priv.]
CVE-2022-49359
Assisted-by: kybele:claude-opus-4.8
Signed-off-by: Cengiz Can <cengiz.can at canonical.com>
---
drivers/gpu/drm/panfrost/panfrost_drv.c | 5 +++--
drivers/gpu/drm/panfrost/panfrost_job.c | 11 ++++++-----
drivers/gpu/drm/panfrost/panfrost_job.h | 5 +++--
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 80dbb9a02f97..3a9a08b415ba 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -242,6 +242,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;
@@ -273,7 +274,7 @@ 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;
ret = panfrost_copy_in_sync(dev, file, args, job);
if (ret)
@@ -283,7 +284,7 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data,
if (ret)
goto fail_job;
- ret = panfrost_job_push(job);
+ ret = panfrost_job_push(file_priv, job);
if (ret)
goto fail_job;
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index 71a72fb50e6b..845e0c13fcf8 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -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), jc_head & 0xFFFFFFFF);
job_write(pfdev, JS_HEAD_NEXT_HI(js), jc_head >> 32);
@@ -266,11 +266,12 @@ static void panfrost_attach_object_fences(struct drm_gem_object **bos,
dma_resv_add_excl_fence(bos[i]->resv, fence);
}
-int panfrost_job_push(struct panfrost_job *job)
+int panfrost_job_push(struct panfrost_file_priv *file_priv,
+ struct panfrost_job *job)
{
struct panfrost_device *pfdev = job->pfdev;
int slot = panfrost_job_get_slot(job);
- struct drm_sched_entity *entity = &job->file_priv->sched_entity[slot];
+ struct drm_sched_entity *entity = &file_priv->sched_entity[slot];
struct ww_acquire_ctx acquire_ctx;
int ret = 0;
@@ -456,7 +457,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)
@@ -477,7 +478,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);
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.h b/drivers/gpu/drm/panfrost/panfrost_job.h
index 82306a03b57e..5fa184aa6d66 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.h
+++ b/drivers/gpu/drm/panfrost/panfrost_job.h
@@ -17,7 +17,7 @@ struct panfrost_job {
struct kref refcount;
struct panfrost_device *pfdev;
- struct panfrost_file_priv *file_priv;
+ struct panfrost_mmu *mmu;
/* Contains both explicit and implicit fences */
struct xarray deps;
@@ -42,7 +42,8 @@ int panfrost_job_init(struct panfrost_device *pfdev);
void panfrost_job_fini(struct panfrost_device *pfdev);
int panfrost_job_open(struct panfrost_file_priv *panfrost_priv);
void panfrost_job_close(struct panfrost_file_priv *panfrost_priv);
-int panfrost_job_push(struct panfrost_job *job);
+int panfrost_job_push(struct panfrost_file_priv *file_priv,
+ struct panfrost_job *job);
void panfrost_job_put(struct panfrost_job *job);
void panfrost_job_enable_interrupts(struct panfrost_device *pfdev);
int panfrost_job_is_idle(struct panfrost_device *pfdev);
--
2.53.0
More information about the kernel-team
mailing list