All of lore.kernel.org
 help / color / mirror / Atom feed
From: Breno Leitao <leitao@debian.org>
To: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Tejun Heo <tj@kernel.org>, Lai Jiangshan <jiangshanlai@gmail.com>,
	 Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>,
	clm@fb.com, linux-kernel@vger.kernel.org, kernel-team@meta.com
Subject: Re: [PATCH] workqueue: fix devm_alloc_workqueue() va_list misuse
Date: Tue, 28 Apr 2026 07:59:52 -0700	[thread overview]
Message-ID: <afDLWm3ekzjqY52S@gmail.com> (raw)
In-Reply-To: <ae-iGjtN5LFfGR6W@ashevche-desk.local>

On Mon, Apr 27, 2026 at 08:51:22PM +0300, Andy Shevchenko wrote:
> On Mon, Apr 27, 2026 at 09:47:44AM -0700, Breno Leitao wrote:
> > devm_alloc_workqueue() builds a va_list from its own variadic
> > arguments and then passes that va_list as a single positional
> > argument to the variadic alloc_workqueue() macro:
> > 
> > 	va_start(args, max_active);
> > 	wq = alloc_workqueue(fmt, flags, max_active, args);
> > 	va_end(args);
> > 
> > alloc_workqueue() expands to alloc_workqueue_noprof(), which
> > performs its own va_start() over its ... parameters. The inner
> > vsnprintf(wq->name, sizeof(wq->name), fmt, args) inside
> > __alloc_workqueue() therefore receives the outer va_list object
> > as the first variadic slot, not the caller's actual format
> > arguments. On x86-64 SysV a "%s" conversion dereferences the
> > pointer inside that va_list as a char * and copies arbitrary
> > stack bytes from devm_alloc_workqueue()'s register-save area
> > into wq->name. The write is bounded by WQ_NAME_LEN but the
> > read is not, so this is an out-of-bounds stack read whose result
> > also surfaces via show_all_workqueues(), print_worker_info(),
> > the WQ_NAME_LEN pr_warn_once(), and lockdep lock names.
> > 
> > C does not allow forwarding a va_list through a ... parameter;
> > a v-style entry point is required. __alloc_workqueue() is
> > exactly that and is already used by alloc_workqueue_noprof().
> > Split devm_alloc_workqueue() into devm_alloc_workqueue_noprof()
> > plus an alloc_hooks() macro wrapper, mirroring the
> > alloc_workqueue / alloc_workqueue_noprof split. The _noprof
> > function calls __alloc_workqueue() directly with the va_list we
> > already hold, and runs wq_init_lockdep(wq) afterwards to mirror
> > alloc_workqueue_noprof() (otherwise wq->lockdep_map stays NULL
> > and __flush_workqueue()'s on-stack
> > COMPLETION_INITIALIZER_ONSTACK_MAP would NULL-deref it).
> > 
> > Keeping the alloc_hooks() wrapper preserves memory allocation
> > profiling attribution under CONFIG_MEM_ALLOC_PROFILING=y: the
> > kzalloc_noprof() and alloc_workqueue_attrs_noprof() inside
> > __alloc_workqueue() are charged to the driver call site rather
> > than to a single line in kernel/workqueue.c.
> > 
> > No caller changes are required. Drivers continue to write
> > devm_alloc_workqueue() and devm_alloc_ordered_workqueue() as
> > before; the new macro forwards through alloc_hooks() into the
> > renamed _noprof function transparently. Out-of-tree modules
> > need only be recompiled against the updated header to pick up
> > the renamed export, mirroring the precedent set by the existing
> > alloc_workqueue / alloc_workqueue_noprof split.
> > 
> > devm_alloc_ordered_workqueue() in include/linux/workqueue.h is
> > a macro that forwards to devm_alloc_workqueue(), so it inherits
> > this fix automatically. 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]
> 
> > 
> 
> There shouldn't be blank line(s) in the tag block.

Ack, I will remove it in the respin.

> 
> > Fixes: 1dfc9d60a69e ("workqueue: devres: Add device-managed allocate workqueue")
> > Signed-off-by: Breno Leitao <leitao@debian.org>
> 
> Otherwise second Tejun's "nice catch"!

      reply	other threads:[~2026-04-28 15:00 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-27 16:47 [PATCH] workqueue: fix devm_alloc_workqueue() va_list misuse Breno Leitao
2026-04-27 17:29 ` Tejun Heo
2026-04-28 15:00   ` Breno Leitao
2026-04-27 17:51 ` Andy Shevchenko
2026-04-28 14:59   ` Breno Leitao [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afDLWm3ekzjqY52S@gmail.com \
    --to=leitao@debian.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=clm@fb.com \
    --cc=jiangshanlai@gmail.com \
    --cc=kernel-team@meta.com \
    --cc=krzysztof.kozlowski@oss.qualcomm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.