All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Puranjay Mohan" <puranjay@kernel.org>
Cc: bpf@vger.kernel.org, linux-rt-devel@lists.linux.dev,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 1/6] rcu: Make call_rcu() safe to call from any context
Date: Mon, 10 Aug 2026 12:43:50 +0000	[thread overview]
Message-ID: <20260810124351.390741F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260810122758.183765-2-puranjay@kernel.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Deferred callbacks bypass `debug_rcu_head_queue()` check, causing immediate list corruption on double `call_rcu()` and defeating `CONFIG_DEBUG_OBJECTS_RCU_HEAD`.
--

--- Patch [1]: [PATCH v4 1/6] rcu: Make call_rcu() safe to call from any context ---
commit 5205f0afe602a3f93ee865a26d94981f93553b7d
Author: Puranjay Mohan <puranjay@kernel.org>

rcu: Make call_rcu() safe to call from any context

This patch defers call_rcu() via a per-CPU llist and irq_work when called
with interrupts disabled. This avoids deadlocks or list corruption if
call_rcu() is invoked from NMI or instrumentation.

> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index 96848fc1f02b8..ff9a2395c9e8e 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c

[ ... ]

> -static void
> -__call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> +/*
> + * Also called by __rcu_defer_drain() to re-issue a deferred callback, so it
> + * must not re-check the deferral condition.  Either caller may have interrupts
> + * already disabled, and a drain of a remote CPU re-issues onto the draining
> + * CPU.
> + */
> +static void rcu_do_enqueue(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
>  {
>  	static atomic_t doublefrees;
>  	unsigned long flags;
>  	bool lazy;
>  	struct rcu_data *rdp;
>  
> -	/* Misaligned rcu_head! */
> -	WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1));
> -
> -	/* Avoid NULL dereference if callback is NULL. */
> -	if (WARN_ON_ONCE(!func))
> -		return;
> -
>  	if (debug_rcu_head_queue(head)) {

[ ... ]

> +static void call_rcu_defer(struct rcu_head *head, rcu_callback_t func)
> +{
> +	struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
> +
> +	/*
> +	 * Instrumentation on the enqueue path can re-enter here from inside the
> +	 * drain.  Re-queuing would livelock it, so drop the callback; an NMI
> +	 * cannot loop, so let it through.
> +	 */
> +	if (READ_ONCE(rdp->defer_draining) && !in_nmi()) {
> +		WARN_ONCE(IS_ENABLED(CONFIG_PROVE_RCU),
> +			  "call_rcu() re-entered during callback drain; leaking callback\n");
> +		return;
> +	}
> +	head->func = func;
> +	if (llist_add((struct llist_node *)head, &rdp->defer_head))
> +		irq_work_queue(&rdp->defer_work);
> +}

[ ... ]

> +static void
> +__call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> +{
> +	/* Misaligned rcu_head! */
> +	WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1));
> +
> +	/* Avoid NULL dereference if callback is NULL. */
> +	if (WARN_ON_ONCE(!func))
> +		return;
> +
> +	/* Record the caller: the irq_work's stack says nothing about it. */
> +	kasan_record_aux_stack(head);
> +
> +	if (should_rcu_defer()) {
> +		call_rcu_defer(head, func);

[Severity: High]
Does this bypass the debug check for double call_rcu(), potentially corrupting
the callback list?

By moving debug_rcu_head_queue() from __call_rcu_common() into rcu_do_enqueue(),
deferred callbacks are added to the defer_head list before being validated.

If a double call_rcu() occurs, llist_add() in call_rcu_defer() will overwrite
head->next. If the callback was already in a normal cblist, its next pointer is
overwritten with defer_head->first, immediately splitting the cblist and
splicing it into the deferred list.

Could we check debug_rcu_head_queue() here before deferring, so that
CONFIG_DEBUG_OBJECTS_RCU_HEAD can safely catch the bug without list corruption?

> +		return;
> +	}
> +
> +	/*
> +	 * Only reachable from an NMI when deferral is off: before the scheduler
> +	 * is up, or with CONFIG_RCU_DEFER=n.  The enqueue can then race.
> +	 */
> +	WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi());
> +
> +	rcu_do_enqueue(head, func, lazy_in);
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260810122758.183765-1-puranjay@kernel.org?part=1

  reply	other threads:[~2026-08-10 12:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10 12:27 [PATCH v4 0/6] rcu,srcu: Make call_rcu()/call_srcu() safe from any context Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 1/6] rcu: Make call_rcu() safe to call " Puranjay Mohan
2026-08-10 12:43   ` sashiko-bot [this message]
2026-08-10 12:48     ` Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 2/6] rcu: Make Tiny " Puranjay Mohan
2026-08-10 12:42   ` sashiko-bot
2026-08-10 12:45     ` Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 3/6] srcu: Make call_srcu() " Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 4/6] srcu: Make Tiny " Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 5/6] rcutorture: Exercise ->call() from NMI context Puranjay Mohan
2026-08-10 12:27 ` [PATCH v4 6/6] selftests/bpf: Add a call_srcu() re-entry reproducer Puranjay Mohan
2026-08-12  0:10 ` [PATCH v4 0/6] rcu,srcu: Make call_rcu()/call_srcu() safe from any context Paul E. McKenney

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=20260810124351.390741F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=puranjay@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.