On 2026-10-27 18:38, Ian Rogers wrote:
struct queue embeds a struct kobject (q->kobj) for procfs entries, but
procfs_queue_type had no .release callback and uninit_queue() freed q
immediately after kfd_procfs_del_queue() called kobject_put(&q->kobj).
With CONFIG_DEBUG_KOBJECT_RELEASE=y, this causes a use-after-free.

Add kfd_procfs_queue_release() to free struct queue from the kobject
release callback, change kfd_procfs_del_queue() to only remove the
kobject from sysfs via kobject_del(), and drop the final reference in
uninit_queue() via kobject_put(). Check q->kobj.state_in_sysfs before
calling kobject_del() in kfd_procfs_del_queue() to avoid warnings if
sysfs creation previously failed.

Fixes: 6d220a7e7971 ("drm/amdkfd: Add queue information to sysfs")
Signed-off-by: Ian Rogers <[email protected]>

Reviewed-by: Felix Kuehling <[email protected]>


---
  drivers/gpu/drm/amd/amdkfd/kfd_process.c | 12 +++++++++---
  drivers/gpu/drm/amd/amdkfd/kfd_queue.c   |  5 ++++-
  2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 226f52626e84..8e6136d52a50 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {
        .show = kfd_procfs_queue_show,
  };
+static void kfd_procfs_queue_release(struct kobject *kobj)
+{
+       struct queue *q = container_of(kobj, struct queue, kobj);
+
+       kfree(q);
+}
+
  static const struct kobj_type procfs_queue_type = {
+       .release = kfd_procfs_queue_release,
        .sysfs_ops = &procfs_queue_ops,
        .default_groups = procfs_queue_groups,
  };
@@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)
        if (ret < 0) {
                pr_warn("Creating proc/<pid>/queues/%u failed",
                        q->properties.queue_id);
-               kobject_put(&q->kobj);
                return ret;
        }
@@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p) void kfd_procfs_del_queue(struct queue *q)
  {
-       if (!q || !q->process->kobj)
+       if (!q || !q->process || !q->process->kobj || !q->kobj.state_in_sysfs)
                return;
kobject_del(&q->kobj);
-       kobject_put(&q->kobj);
  }
int kfd_process_create_wq(void)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index ae3e7c54014a..4666110aebe0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -83,7 +83,10 @@ int init_queue(struct queue **q, const struct 
queue_properties *properties)
void uninit_queue(struct queue *q)
  {
-       kfree(q);
+       if (q && q->kobj.state_initialized)
+               kobject_put(&q->kobj);
+       else
+               kfree(q);
  }
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)

Reply via email to