From nobody Wed Jun 17 01:37:53 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02742243951 for ; Tue, 28 Apr 2026 15:14:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777389267; cv=none; b=YsuCE60xfWe9nK7m6k6mvQoz4LHo/WPVherV/fu7XrfaoDUjP0RXQ7O8p+IlR4mozMxb3ctHmqvemCghU/Drmdp9v3bm9WETIWJ+qFBYdWLVQ4WYwTviYZAEymIPGLkXBnGelDbSiA1N5fu9VBDnfpaSa5QdBKCheP2PqBaPj2U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777389267; c=relaxed/simple; bh=miCk1qdRmyBJPKNd8kvCS8ugjaRIi8gdVtMGqguv1N4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=XNxE2TVGWZp7/aM3zLrdfYACOZGEAV0BKbD+1Q//e5vBkIFwozgD4ivfP44Oe4TgyYxahp33kwqj/zZfKZFW+zvECJ7b/dnw0jguZsKHwbvM0fVeKFYwVZ3H5oyqNfTQSKhq2rvFuiicy2Nb9/fzDkdYTcQCvyMQN1yPfY5kCvc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=lwszAfei; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="lwszAfei" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From: Reply-To:Content-ID:Content-Description:In-Reply-To:References; bh=lx87awzeuGt5ROr2rJEy44vz0Irb6WhDJ/RLmKC+pIY=; b=lwszAfeiD1tkhVUTSVPDSWWmHm u/llOyS/Xh5PTOSCIwvDVgudGRwbVG62lXhiV8VUF2QUWfK9q9BYUAlcugtiDiTDVh/RF4ljjdfNp ksdTDJgzWx2bYsZd7nMbyqw1jXxjqqcCqDdvxLS4dlLIS8TnJ2OK2f8eVNnCT+YI1LVhINyU9s9Te 18NfByDwfX9ZGtf/qe5vUnUfdqeX213YayuXoaDkoagifprMU+6CxCSJmKbxPDSng44B0D98LaTXQ WPIuuPst4JZ2kkgLJb5wk6zBoFQBpDES4zpwBzfzYrNmplu++vcU/QpPDn839TbdbmUR9jkE8ppIg CUWNWXEQ==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.96) (envelope-from ) id 1wHk8d-006LQH-0S; Tue, 28 Apr 2026 15:14:16 +0000 From: Breno Leitao Date: Tue, 28 Apr 2026 08:10:43 -0700 Subject: [PATCH v2] workqueue: fix devm_alloc_workqueue() va_list misuse Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260428-wq_fix_chris-v2-1-c02eac6ab31d@debian.org> X-B4-Tracking: v=1; b=H4sIAPLN8GkC/3XNQQ6CMBCF4as0s6YGpg20rLyHIaSUAcYFaIuII dzdgGuXL/nzvQ0iBaYIpdgg0MKRpxFKgYkAP7ixJ8ktlAIwxTzVWMj3s+54rf0QOEpCRUqj8tY pSAQ8AnW8ntyt+u34au7k58M4ioHjPIXP+bdkR/eHXjKZSWtMrq1RuinstaWG3XiZQg/Vvu9fm BESobsAAAA= X-Change-ID: 20260427-wq_fix_chris-e23e3423c9a3 To: Tejun Heo , Lai Jiangshan , Andy Shevchenko , Krzysztof Kozlowski Cc: clm@fb.com, linux-kernel@vger.kernel.org, kernel-team@meta.com, Breno Leitao X-Mailer: b4 0.16-dev-453a6 X-Developer-Signature: v=1; a=openpgp-sha256; l=4828; i=leitao@debian.org; h=from:subject:message-id; bh=miCk1qdRmyBJPKNd8kvCS8ugjaRIi8gdVtMGqguv1N4=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBp8M7DadEIh9um0RlaiPZCV1TyzktVgrxcdeQQQ KiwJhohtDGJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCafDOwwAKCRA1o5Of/Hh3 baZLEACPM7ofhT8Z00BXskJ2TJeZelSvajPLB3whKov6aO1Zc55BdAsCbZpGkmJCkXkwLWtYowf P/pRFRAXy6o+wMwBUIxlw4Qur/2df1U9xt9PzJQm56qn9h1iAXRWUyOUp/zqgymV/dOv3g6FL8c iHNHbLY3GO6wJGZWx+YgcVRxM844QJ/CjoWRoEzj9H4B1BTX2n98cqeTeUcl8lUc6QLda14HrDX ZlJnvw5ASezzNIoNDftZQe9oy0LjltCFodVxeKRayqvztlAJIleqay38AVbeiNZWNJTqmfkFYNz OJsujJeKwNhDKZJP+IapNe6sts6u0yIrK4sg8jUZRGXYTpc3bWfLMVKQa2yYKFof0StByCMUBHr tllv6zxRm4TRq9mGojDcqhQQ4Mptd0aUu9+3nZCXdMhNTmM4LJI+b2zSjdofVLB2B/cC+6ueb1y o8DA5IgxVyue3PrZOmNtvbQxQyJOP2FrBqDvWzkDRLdZj8pUdEPq6x/KE6obsdA/SopAOx+HcVg X8aPzDl3ipAPsmeQIKnCH+jLOm+0FiEoTGJt94WlJ+YEoqZRvEnP9Suj52URfM0rC3AfPqpCc+N wZlETdW7kj1b6cyJN2H7FXvo+/t5PjCBBxb6Are9p1SlKKPvtTUtIEdlmv8fOv72k7N1uIvU7Ms 803OOCJryBirAuw== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao devm_alloc_workqueue() built a va_list and passed it as a single positional argument to the variadic alloc_workqueue() macro: va_start(args, max_active); wq =3D alloc_workqueue(fmt, flags, max_active, args); va_end(args); C does not allow forwarding a va_list through a ... parameter. alloc_workqueue() expands to alloc_workqueue_noprof(), which runs its own va_start() over its ... params, so the inner vsnprintf(wq->name, sizeof(wq->name), fmt, args) in __alloc_workqueue() received the outer va_list object as the first variadic slot rather than the caller's actual format arguments. Add a new static helper alloc_workqueue_va() that wraps __alloc_workqueue() and runs wq_init_lockdep() on success, and fold both alloc_workqueue_noprof() and devm_alloc_workqueue_noprof() onto it as suggested by Tejun. The wq_init_lockdep() step is required on the devm path too, otherwise __flush_workqueue()'s on-stack COMPLETION_INITIALIZER_ONSTACK_MAP would NULL-deref wq->lockdep_map. No caller changes are required. devm_alloc_ordered_workqueue() is a macro forwarding to devm_alloc_workqueue() and inherits the fix. Two in-tree callers actively trigger the broken path on every probe: drivers/power/supply/mt6370-charger.c:889 drivers/power/supply/max77705_charger.c:649 both of which use devm_alloc_ordered_workqueue(dev, "%s", 0, dev_name(dev)). A standalone reproducer module is available at[1]. Link: https://github.com/leitao/debug/blob/main/workqueue/valist/wq_va_test= .c [1] Fixes: 1dfc9d60a69e ("workqueue: devres: Add device-managed allocate workqu= eue") Signed-off-by: Breno Leitao --- Changes in v2: - Fold both noprof entries onto a shared helper (alloc_workqueue_va) (Tejun) - Link to v1: https://patch.msgid.link/20260427-wq_fix_chris-v1-1-988649834= b79@debian.org --- include/linux/workqueue.h | 6 ++++-- kernel/workqueue.c | 28 +++++++++++++++++++--------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index ab6cb70ca1a52..6177624539b3b 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -534,8 +534,10 @@ alloc_workqueue_noprof(const char *fmt, unsigned int f= lags, int max_active, ...) * Pointer to the allocated workqueue on success, %NULL on failure. */ __printf(2, 5) struct workqueue_struct * -devm_alloc_workqueue(struct device *dev, const char *fmt, unsigned int fla= gs, - int max_active, ...); +devm_alloc_workqueue_noprof(struct device *dev, const char *fmt, + unsigned int flags, int max_active, ...); +#define devm_alloc_workqueue(...) \ + alloc_hooks(devm_alloc_workqueue_noprof(__VA_ARGS__)) =20 #ifdef CONFIG_LOCKDEP /** diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 5f747f241a5f1..24d0265191d46 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5906,6 +5906,20 @@ static struct workqueue_struct *__alloc_workqueue(co= nst char *fmt, return NULL; } =20 +static struct workqueue_struct *alloc_workqueue_va(const char *fmt, + unsigned int flags, + int max_active, + va_list args) +{ + struct workqueue_struct *wq; + + wq =3D __alloc_workqueue(fmt, flags, max_active, args); + if (wq) + wq_init_lockdep(wq); + + return wq; +} + __printf(1, 4) struct workqueue_struct *alloc_workqueue_noprof(const char *fmt, unsigned int flags, @@ -5915,12 +5929,8 @@ struct workqueue_struct *alloc_workqueue_noprof(cons= t char *fmt, va_list args; =20 va_start(args, max_active); - wq =3D __alloc_workqueue(fmt, flags, max_active, args); + wq =3D alloc_workqueue_va(fmt, flags, max_active, args); va_end(args); - if (!wq) - return NULL; - - wq_init_lockdep(wq); =20 return wq; } @@ -5932,15 +5942,15 @@ static void devm_workqueue_release(void *res) } =20 __printf(2, 5) struct workqueue_struct * -devm_alloc_workqueue(struct device *dev, const char *fmt, unsigned int fla= gs, - int max_active, ...) +devm_alloc_workqueue_noprof(struct device *dev, const char *fmt, + unsigned int flags, int max_active, ...) { struct workqueue_struct *wq; va_list args; int ret; =20 va_start(args, max_active); - wq =3D alloc_workqueue(fmt, flags, max_active, args); + wq =3D alloc_workqueue_va(fmt, flags, max_active, args); va_end(args); if (!wq) return NULL; @@ -5951,7 +5961,7 @@ devm_alloc_workqueue(struct device *dev, const char *= fmt, unsigned int flags, =20 return wq; } -EXPORT_SYMBOL_GPL(devm_alloc_workqueue); +EXPORT_SYMBOL_GPL(devm_alloc_workqueue_noprof); =20 #ifdef CONFIG_LOCKDEP __printf(1, 5) --- base-commit: dd6c438c3e64a5ff0b5d7e78f7f9be547803ef1b change-id: 20260427-wq_fix_chris-e23e3423c9a3 Best regards, -- =20 Breno Leitao