On 12/07/2026 16:14, Maíra Canal wrote:
This is a preparation commit for per-file descriptor seqno tracking,
which will require the struct vc4_render_job to store a pointer to
vc4_file. Since the scheduler's free_job callback runs asynchronously,
it can execute after vc4_close() has already freed the vc4_file, causing
a use-after-free.
Add kref-based reference counting to vc4_file so that jobs can safely
take a reference at submit time via vc4_file_get() and drop it in their
free callback via vc4_file_put().
Signed-off-by: Maíra Canal <[email protected]>
---
drivers/gpu/drm/vc4/vc4_drv.c | 12 ++++++++++--
drivers/gpu/drm/vc4/vc4_drv.h | 17 +++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index cacd4cb94259..6c49304301c9 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -167,6 +167,7 @@ static int vc4_open(struct drm_device *dev, struct drm_file
*file)
goto err_sched;
}
+ kref_init(&vc4file->refcount);
vc4_perfmon_open_file(vc4file);
file->driver_priv = vc4file;
@@ -180,6 +181,14 @@ static int vc4_open(struct drm_device *dev, struct drm_file *file)
}
+void vc4_file_release(struct kref *ref)
+{
+ struct vc4_file *vc4file = container_of(ref, struct vc4_file, refcount);
+
+ vc4_perfmon_close_file(vc4file);
+ kfree(vc4file);
+}
+
static void vc4_close(struct drm_device *dev, struct drm_file *file)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -195,8 +204,7 @@ static void vc4_close(struct drm_device *dev, struct
drm_file *file)
for (q = 0; q < VC4_MAX_QUEUES; q++)
drm_sched_entity_destroy(&vc4file->sched_entity[q]);
- vc4_perfmon_close_file(vc4file);
- kfree(vc4file);
+ vc4_file_put(vc4file);
}
DEFINE_DRM_GEM_FOPS(vc4_drm_fops);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 255a95f55586..4f452ea3b4a6 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -905,6 +905,8 @@ struct vc4_exec_info {
struct vc4_file {
struct vc4_dev *dev;
+ struct kref refcount;
+
struct xarray perfmons;
struct drm_sched_entity sched_entity[VC4_MAX_QUEUES];
@@ -1092,6 +1094,21 @@ static inline void vc4_debugfs_add_regset32(struct
drm_device *drm,
/* vc4_drv.c */
void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
int vc4_dumb_fixup_args(struct drm_mode_create_dumb *args);
+void vc4_file_release(struct kref *ref);
+
+static inline
+struct vc4_file *vc4_file_get(struct vc4_file *vc4file)
+{
+ kref_get(&vc4file->refcount);
+ return vc4file;
+}
+
+static inline
+void vc4_file_put(struct vc4_file *vc4file)
+{
+ kref_put(&vc4file->refcount, vc4_file_release);
+}
+
/* vc4_dpi.c */
extern struct platform_driver vc4_dpi_driver;
Reviewed-by: Tvrtko Ursulin <[email protected]>
Regards,
Tvrtko