mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user