From 9d4815c14f7faf789aeaa63515024168daf0390c Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 11 Sep 2026 03:26:28 -0700 Subject: [PATCH] workqueue: BUG_ON() a pwq release before workqueue_init() put_pwq() bounces the release to pwq_release_worker to get out from under pool->lock. workqueue_init() creates that kthread_worker well after workqueue_init_early() has built the system workqueues, so a pwq allocation failing partway through apply_wqattrs_prepare() unwinds through apply_wqattrs_cleanup() and dereferences a NULL worker. There is no way back from that. Running the release inline is not an option, that is what the bounce exists for, and workqueue_init_early() already BUG_ON()s a system workqueue it failed to allocate. BUG_ON() the missing worker instead of oopsing inside kthread_queue_work(). Suggested-by: Tejun Heo Link: https://lore.kernel.org/all/144b3dc986135ebe34f671cdd02bd8aa@kernel.org/ Signed-off-by: Breno Leitao Signed-off-by: Tejun Heo --- kernel/workqueue.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 39187f424c34..e618108c6127 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1771,6 +1771,14 @@ static void put_pwq(struct pool_workqueue *pwq) lockdep_assert_held(&pwq->pool->lock); if (likely(--pwq->refcnt)) return; + + /* + * pwq_release_worker is only created in workqueue_init(). Getting + * here before that means an early workqueue allocation failed, which + * is fatal anyway. + */ + BUG_ON(!pwq_release_worker); + /* * @pwq can't be released under pool->lock, bounce to a dedicated * kthread_worker to avoid A-A deadlocks.