summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarad Gautam <varadgautam@google.com>2022-07-03 17:09:36 +0000
committerVarad Gautam <varadgautam@google.com>2022-07-04 11:36:36 +0000
commit8cf6f3dab19f0b0a2bad43c1385bb957c76c6752 (patch)
treebc51953541c9dbf0c1a8f16304635b003b7dfaed
parentbce3f96102d290ce5f0c7bcee90f4211998b9075 (diff)
downloadgpu-8cf6f3dab19f0b0a2bad43c1385bb957c76c6752.tar.gz
mali_kbase: csf: Prevent kthread leak in kbase_csf_ctx_init error path
kbase_csf_ctx_init() creates and wakes up a realtime kthread (mali_submit) and continues on to initialize csf context. The kthread_worker arg passed to kthread_work_fn() for mali_submit lives within the associated kctx (kctx->csf.pending_submission_worker). If csf context initialization fails, kbase_csf_ctx_init() returns to kbase_create_context(), which frees the associated kctx via kbase_context_term_partial(). This leads to the following race between kctx free and the kthread_worker arg access by mali_submit's kthread_worker_fn call: T1(kbase_create_context): T2(mali_submit): kbase_csf_ctx_init() kbase_create_realtime_thread("mali_submit") kthread_create(kthread_worker_fn) wake_up_process() err = kbase_csf_scheduler_context_init() // -ENOMEM destroy_workqueue(kctx->csf.wq); kbase_context_term_partial() kbase_context_free() vfree(kctx) kthread_worker_fn() WARN_ON(worker->task && worker->task != current) // worker is invalid, oops Stop mali_submit kthread before erroring out from kbase_csf_ctx_init() to close this race. Bug: 234054582 Test: Forced -ENOMEM from kbase_csf_scheduler_context_init. The kernel crashed within 5mins of boot without this patch, and survives with it. Change-Id: I1c31ea7c0c914d7ca84630cb7fd1e20b6595d69c Signed-off-by: Varad Gautam <varadgautam@google.com>
-rw-r--r--mali_kbase/csf/mali_kbase_csf.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/mali_kbase/csf/mali_kbase_csf.c b/mali_kbase/csf/mali_kbase_csf.c
index 0fe8160..d045df8 100644
--- a/mali_kbase/csf/mali_kbase_csf.c
+++ b/mali_kbase/csf/mali_kbase_csf.c
@@ -1765,7 +1765,7 @@ int kbase_csf_ctx_init(struct kbase_context *kctx)
err = kbase_csf_scheduler_context_init(kctx);
if (unlikely(err))
- goto out_err_kthread;
+ goto out_err_scheduler_context;
err = kbase_csf_kcpu_queue_context_init(kctx);
if (unlikely(err))
@@ -1785,6 +1785,8 @@ out_err_tiler_heap_context:
kbase_csf_kcpu_queue_context_term(kctx);
out_err_kcpu_queue_context:
kbase_csf_scheduler_context_term(kctx);
+out_err_scheduler_context:
+ kthread_stop(kctx->csf.pending_sub_worker_thread);
out_err_kthread:
destroy_workqueue(kctx->csf.wq);
out: