summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarad Gautam <varadgautam@google.com>2023-09-27 13:34:16 +0000
committerVarad Gautam <varadgautam@google.com>2023-09-29 15:30:32 +0000
commit241a3cfc12f8b45de331964b5f1a26712b64f6f5 (patch)
tree6559501c3c2adce9d36fd2fbcc778463b19fb64c
parentf92aa3aad510c5a15d91e516f1ed8f45bfc40be0 (diff)
downloadgpu-241a3cfc12f8b45de331964b5f1a26712b64f6f5.tar.gz
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 <varadgautam@google.com>
-rw-r--r--mali_kbase/context/mali_kbase_context.c1
-rw-r--r--mali_kbase/mali_kbase_core_linux.c9
-rw-r--r--mali_kbase/mali_kbase_defs.h8
3 files changed, 9 insertions, 9 deletions
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;