MALI: bifrost: Fix kctx kobj UAF

In a multi kctx scenario, the kobj is freed when one kctx is released,
but the node remains. Accessing it leads to a use-after-free
(invalid pointer) issue.

Fixes: fe59c73bbf ("MALI: bifrost: Optimize gpu mem sysfs entry")
Signed-off-by: Weixin Zhou <zwx@rock-chips.com>
Change-Id: I9d00b660c4ca4693606fbf4f70888cf6809a781d
This commit is contained in:
Weixin Zhou
2025-06-19 11:09:50 +08:00
committed by Tao Huang
parent d91c7665f9
commit 1d7e45abc3
2 changed files with 8 additions and 8 deletions

View File

@@ -84,15 +84,14 @@ static ssize_t kbase_kctx_attr_show(struct kobject *kobj, struct attribute *attr
static ssize_t kbase_total_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct kbase_context *kctx = container_of(kobj, struct kbase_context, kobj);
struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj);
return scnprintf(buf, PAGE_SIZE, "%zu\n", kctx->kprcs->total_gpu_pages << PAGE_SHIFT);
return scnprintf(buf, PAGE_SIZE, "%zu\n", kprcs->total_gpu_pages << PAGE_SHIFT);
}
static ssize_t kbase_private_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct kbase_context *kctx = container_of(kobj, struct kbase_context, kobj);
struct kbase_process *kprcs = kctx->kprcs;
struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj);
struct kbase_context *tmp_kctx;
size_t total_pages = 0;
@@ -183,10 +182,10 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx)
if (unlikely(!scnprintf(kctx_name, 64, "%d", tgid)))
return -ENOMEM;
ret = kobject_init_and_add(&kctx->kobj, &kbase_kctx_ktype, kctx->kbdev->kprcs_kobj, kctx_name);
ret = kobject_init_and_add(&kprcs->kobj, &kbase_kctx_ktype, kctx->kbdev->kprcs_kobj, kctx_name);
if (ret) {
dev_err(kctx->kbdev->dev, "Failed to create kctx kobject");
kobject_put(&kctx->kobj);
kobject_put(&kprcs->kobj);
}
while (*new) {
@@ -340,7 +339,7 @@ static void kbase_remove_kctx_from_process(struct kbase_context *kctx)
* we can remove it from the process rb_tree.
*/
if (list_empty(&kprcs->kctx_list)) {
kobject_put(&kctx->kobj);
kobject_put(&kprcs->kobj);
rb_erase(&kprcs->kprcs_node, &kctx->kbdev->process_root);
/* Add checks, so that the terminating process Should not
* hold any gpu_memory.

View File

@@ -688,6 +688,7 @@ struct kbase_devfreq_queue_info {
/**
* struct kbase_process - Representing an object of a kbase process instantiated
* when the first kbase context is created under it.
* @kobj: Kernel object for sysfs representation of the process.
* @tgid: Thread group ID.
* @total_gpu_pages: Total gpu pages allocated across all the contexts
* of this process, it accounts for both native allocations
@@ -703,6 +704,7 @@ struct kbase_devfreq_queue_info {
* imported multiple times for the process.
*/
struct kbase_process {
struct kobject kobj;
pid_t tgid;
size_t total_gpu_pages;
struct list_head kctx_list;
@@ -1902,7 +1904,6 @@ struct kbase_sub_alloc {
* is made on the device file.
*/
struct kbase_context {
struct kobject kobj;
struct file *filp;
struct kbase_device *kbdev;
struct list_head kctx_list_link;