* [PATCH] workqueue: unlink pwqs from wq->pwqs list in alloc_and_link_pwqs() error path
@ 2026-03-23 10:18 Breno Leitao
2026-03-23 18:35 ` Tejun Heo
0 siblings, 1 reply; 3+ messages in thread
From: Breno Leitao @ 2026-03-23 10:18 UTC (permalink / raw)
To: Tejun Heo, Lai Jiangshan; +Cc: linux-kernel, kernel-team, Breno Leitao
When alloc_and_link_pwqs() fails partway through the per-cpu allocation
loop, some pool_workqueues may have already been linked into wq->pwqs
via link_pwq(). The error path frees these pwqs with kmem_cache_free()
but never removes them from the wq->pwqs list, leaving dangling pointers
in the list.
Currently this is not exploitable because the workqueue was never added
to the global workqueues list and the caller frees the wq immediately
after. However, this makes sure that alloc_and_link_pwqs() doesn't leave
any half baked structure, which may have side effect is not properly
used.
Fix this by unlinking each pwq from wq->pwqs before freeing it. No
locking is needed as the workqueue has not been published yet, thus
no concurrency is possible.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
kernel/workqueue.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b77119d71641a..70581fa7b4e24 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5623,8 +5623,16 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
for_each_possible_cpu(cpu) {
struct pool_workqueue *pwq = *per_cpu_ptr(wq->cpu_pwq, cpu);
- if (pwq)
+ if (pwq) {
+ /*
+ * Unlink pwq from wq->pwqs since link_pwq()
+ * may have already added it. wq->mutex is not
+ * needed as the wq has not been published yet.
+ */
+ if (!list_empty(&pwq->pwqs_node))
+ list_del_rcu(&pwq->pwqs_node);
kmem_cache_free(pwq_cache, pwq);
+ }
}
free_percpu(wq->cpu_pwq);
wq->cpu_pwq = NULL;
---
base-commit: c369299895a591d96745d6492d4888259b004a9e
change-id: 20260323-workqueue_link-d1503237f242
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] workqueue: unlink pwqs from wq->pwqs list in alloc_and_link_pwqs() error path
2026-03-23 10:18 [PATCH] workqueue: unlink pwqs from wq->pwqs list in alloc_and_link_pwqs() error path Breno Leitao
@ 2026-03-23 18:35 ` Tejun Heo
2026-03-23 18:38 ` Breno Leitao
0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2026-03-23 18:35 UTC (permalink / raw)
To: Breno Leitao; +Cc: Lai Jiangshan, linux-kernel, kernel-team
Applied to wq/for-7.1 with a minor commit message edit:
"which may have side effect is not properly used"
-> "which may have side effects if not properly cleaned up"
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] workqueue: unlink pwqs from wq->pwqs list in alloc_and_link_pwqs() error path
2026-03-23 18:35 ` Tejun Heo
@ 2026-03-23 18:38 ` Breno Leitao
0 siblings, 0 replies; 3+ messages in thread
From: Breno Leitao @ 2026-03-23 18:38 UTC (permalink / raw)
To: Tejun Heo; +Cc: Lai Jiangshan, linux-kernel, kernel-team
On Mon, Mar 23, 2026 at 08:35:50AM -1000, Tejun Heo wrote:
> Applied to wq/for-7.1 with a minor commit message edit:
>
> "which may have side effect is not properly used"
> -> "which may have side effects if not properly cleaned up"
ack. Thanks for fixing it.
--breno
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-23 18:38 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-23 10:18 [PATCH] workqueue: unlink pwqs from wq->pwqs list in alloc_and_link_pwqs() error path Breno Leitao
2026-03-23 18:35 ` Tejun Heo
2026-03-23 18:38 ` Breno Leitao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox