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().
Fixes: 6d220a7e7971 ("drm/amdkfd: Add queue information to sysfs")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <[email protected]>
---
drivers/gpu/drm/amd/amdkfd/kfd_process.c | 10 ++++++++--
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 5 ++++-
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 0a7c1900da95..6099cb893573 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -510,7 +510,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,
};
@@ -550,7 +558,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;
}
@@ -699,7 +706,6 @@ void kfd_procfs_del_queue(struct queue *q)
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 15eeaaebbbcd..8d1afc5b47e2 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)
--
2.56.0.385.gd3acb90ef8-goog