From 241a3cfc12f8b45de331964b5f1a26712b64f6f5 Mon Sep 17 00:00:00 2001 From: Varad Gautam Date: Wed, 27 Sep 2023 13:34:16 +0000 Subject: mali_kbase: Move epoll-consumed waitqueue to struct kbase_file Storing the waitqueue in struct kbase_context leaves epoll holding a stale pointer to it, which it later attempts to deref and crashes the kernel in: [*][T15976] remove_wait_queue+0x64/0x190 [40350.510681][T15976] ep_unregister_pollwait+0x98/0xe8 Move this waitqueue to struct kbase_file to ensure that it lives long enough during process termination that the ep_unregister_pollwait access is valid (b/302281297). Bug: 300750575 Test: SST: b/302324090#comment4, repro: b/300750575#comment26 Change-Id: Ib161a7d7d4314bb6951bddbd87183a7dc71d5ac0 Signed-off-by: Varad Gautam --- mali_kbase/context/mali_kbase_context.c | 1 - mali_kbase/mali_kbase_core_linux.c | 9 +++++---- mali_kbase/mali_kbase_defs.h | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'mali_kbase') diff --git a/mali_kbase/context/mali_kbase_context.c b/mali_kbase/context/mali_kbase_context.c index 70941ef..d227084 100644 --- a/mali_kbase/context/mali_kbase_context.c +++ b/mali_kbase/context/mali_kbase_context.c @@ -237,7 +237,6 @@ int kbase_context_common_init(struct kbase_context *kctx) spin_lock_init(&kctx->waiting_soft_jobs_lock); INIT_LIST_HEAD(&kctx->waiting_soft_jobs); - init_waitqueue_head(&kctx->event_queue); atomic_set(&kctx->event_count, 0); #if !MALI_USE_CSF diff --git a/mali_kbase/mali_kbase_core_linux.c b/mali_kbase/mali_kbase_core_linux.c index dd8ba7f..75e8023 100644 --- a/mali_kbase/mali_kbase_core_linux.c +++ b/mali_kbase/mali_kbase_core_linux.c @@ -326,6 +326,7 @@ static struct kbase_file *kbase_file_new(struct kbase_device *const kbdev, #if IS_ENABLED(CONFIG_DEBUG_FS) init_waitqueue_head(&kfile->zero_fops_count_wait); #endif + init_waitqueue_head(&kfile->event_queue); } return kfile; } @@ -2501,7 +2502,7 @@ static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, lof goto out; } - if (wait_event_interruptible(kctx->event_queue, + if (wait_event_interruptible(kctx->kfile->event_queue, kbase_event_pending(kctx)) != 0) { err = -ERESTARTSYS; goto out; @@ -2556,7 +2557,7 @@ static __poll_t kbase_poll(struct file *filp, poll_table *wait) goto out; } - poll_wait(filp, &kctx->event_queue, wait); + poll_wait(filp, &kfile->event_queue, wait); if (kbase_event_pending(kctx)) { #if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) ret = POLLIN | POLLRDNORM; @@ -2576,12 +2577,12 @@ void _kbase_event_wakeup(struct kbase_context *kctx, bool sync) if(sync) { dev_dbg(kctx->kbdev->dev, "Waking event queue for context %pK (sync)\n", (void *)kctx); - wake_up_interruptible_sync(&kctx->event_queue); + wake_up_interruptible_sync(&kctx->kfile->event_queue); } else { dev_dbg(kctx->kbdev->dev, "Waking event queue for context %pK (nosync)\n",(void *)kctx); - wake_up_interruptible(&kctx->event_queue); + wake_up_interruptible(&kctx->kfile->event_queue); } } diff --git a/mali_kbase/mali_kbase_defs.h b/mali_kbase/mali_kbase_defs.h index efe690d..255281d 100644 --- a/mali_kbase/mali_kbase_defs.h +++ b/mali_kbase/mali_kbase_defs.h @@ -1599,6 +1599,9 @@ enum kbase_file_state { * present. * @zero_fops_count_wait: Waitqueue used to wait for the @fops_count to become 0. * Currently needed only for the "mem_view" debugfs file. + * @event_queue: Wait queue used for blocking the thread, which consumes + * the base_jd_event corresponding to an atom, when there + * are no more posted events. */ struct kbase_file { struct kbase_device *kbdev; @@ -1614,6 +1617,7 @@ struct kbase_file { #if IS_ENABLED(CONFIG_DEBUG_FS) wait_queue_head_t zero_fops_count_wait; #endif + wait_queue_head_t event_queue; }; #if MALI_JIT_PRESSURE_LIMIT_BASE /** @@ -1835,9 +1839,6 @@ struct kbase_sub_alloc { * used in conjunction with @cookies bitmask mainly for * providing a mechansim to have the same value for CPU & * GPU virtual address. - * @event_queue: Wait queue used for blocking the thread, which consumes - * the base_jd_event corresponding to an atom, when there - * are no more posted events. * @tgid: Thread group ID of the process whose thread created * the context (by calling KBASE_IOCTL_VERSION_CHECK or * KBASE_IOCTL_SET_FLAGS, depending on the @api_version). @@ -2093,7 +2094,6 @@ struct kbase_context { DECLARE_BITMAP(cookies, BITS_PER_LONG); struct kbase_va_region *pending_regions[BITS_PER_LONG]; - wait_queue_head_t event_queue; pid_t tgid; pid_t pid; atomic_t used_pages; -- cgit v1.2.3