]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
workqueue: Fix wq->cpu_pwq leak in alloc_and_link_pwqs() WQ_UNBOUND path
authorBreno Leitao <leitao@debian.org>
Fri, 8 May 2026 16:22:03 +0000 (09:22 -0700)
committerTejun Heo <tj@kernel.org>
Fri, 8 May 2026 17:59:44 +0000 (07:59 -1000)
For WQ_UNBOUND workqueues, alloc_and_link_pwqs() allocates wq->cpu_pwq
via alloc_percpu() and then calls apply_workqueue_attrs_locked(). On
failure it returns the error directly, bypassing the enomem: label
which holds the only free_percpu(wq->cpu_pwq) in this function.

The caller's error path kfree()s wq without touching wq->cpu_pwq,
leaking one percpu pointer table (nr_cpu_ids * sizeof(void *) bytes) per
failed call.

If kmemleak is enabled, we can see:

  unreferenced object (percpu) 0xc0fffa5b121048 (size 8):
    comm "insmod", pid 776, jiffies 4294682844
    backtrace (crc 0):
      pcpu_alloc_noprof+0x665/0xac0
      __alloc_workqueue+0x33f/0xa20
      alloc_workqueue_noprof+0x60/0x100

Route the error through the existing enomem: cleanup and any error
before this one.

Cc: stable@kernel.org
Fixes: 636b927eba5b ("workqueue: Make unbound workqueues to use per-cpu pool_workqueues")
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/workqueue.c

index c0e58f877e0892adfb39b40b47ade9d4fd1ee5f2..33b721a9af022350075e51cf84f23ffe19b60744 100644 (file)
@@ -5654,7 +5654,9 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
                ret = apply_workqueue_attrs_locked(wq, unbound_std_wq_attrs[highpri]);
        }
 
-       return ret;
+       if (ret)
+               goto enomem;
+       return 0;
 
 enomem:
        if (wq->cpu_pwq) {