mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/9] rcu: Improve callback diagnostics and validation
@ 2026-10-23 10:18 Kunwu Chan
  2026-10-23 10:18 ` [PATCH 1/9] srcu: Record callback registration stack for KASAN Kunwu Chan
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel, Kunwu Chan

Hi,

This series improves callback diagnostics and validation across RCU,
SRCU, and RCU Tasks.

Patches 1-3 record callback registration stacks for KASAN in Tree
SRCU, Tiny SRCU, and Tiny RCU, matching the existing behavior in
Tree RCU.  This preserves the original registration site in KASAN
reports when callbacks are deferred through irq_work.

Patches 4-6 add rcu_head alignment and NULL callback-function
checks to SRCU, Tiny RCU, and RCU Tasks, consistent with the
existing checks in Tree RCU.

Patches 7-9 detect duplicate callback enqueue attempts at
registration time, report the callback address, function symbol,
and object information, and limit diagnostics to the first three
occurrences.  In Tree SRCU, moving the check from srcu_do_enqueue()
to __call_srcu() rejects detected duplicate registrations before
they reach the deferred-list enqueue path.

The duplicate-enqueue checks rely on the existing RCU head
debug-object mechanism and are effective only when
CONFIG_DEBUG_OBJECTS_RCU_HEAD is enabled.  They provide
diagnostics, not full protection against concurrent registration
of the same rcu_head, which violates the API contract.

Tested by rcutorture with KASAN enabled: SRCU-N, SRCU-P, SRCU-T,
SRCU-U, TINY01, TINY02, and TREE03, each for 3 minutes.  All
configurations completed with exitcode 0.

The KASAN aux stack was verified with a custom UAF module: the
"Last potentially related work creation" line in the KASAN report
identified the original __call_srcu() registration site.

A targeted Tree SRCU test module exercised duplicate enqueue
detection on both the direct and irqs-off deferred paths with
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.  Both paths rejected the
duplicate at __call_srcu() entry without list corruption or
hangs.

A targeted Tiny SRCU test module exercised NULL callback
rejection, duplicate enqueue detection, and post-callback
rcu_head reuse with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.  The
first two tests produced the expected diagnostics, and the
callback and reuse tests completed without hangs or stale
debug-object state.

RCU Tasks duplicate enqueue detection was verified by code
inspection; no targeted runtime test has been performed for
that path.
 
Kunwu Chan (9):
  srcu: Record callback registration stack for KASAN
  srcutiny: Record callback registration stack for KASAN
  rcu: Record callback registration stack for Tiny RCU
  srcu: Validate callback arguments
  rcu: Validate callback arguments in Tiny RCU
  rcu-tasks: Validate callback arguments
  srcu: Detect duplicate callback enqueue at registration
  srcutiny: Detect duplicate callback enqueue
  rcu-tasks: Detect duplicate callback enqueue

 kernel/rcu/srcutiny.c | 30 ++++++++++++++++++++++++++++++
 kernel/rcu/srcutree.c | 32 ++++++++++++++++++++++++++------
 kernel/rcu/tasks.h    | 22 ++++++++++++++++++++++
 kernel/rcu/tiny.c     | 11 +++++++++++
 4 files changed, 89 insertions(+), 6 deletions(-)


base-commit: 940793b926aa94bf65ec404043050888e3053188
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/9] srcu: Record callback registration stack for KASAN
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 2/9] srcutiny: " Kunwu Chan
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Record the callback registration stack in __call_srcu()
for KASAN diagnostics involving SRCU callbacks.

Suggested-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/srcutree.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index 2b0e2b2d2c18..46fe2f0cef85 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -20,6 +20,7 @@
 #include <linux/percpu.h>
 #include <linux/preempt.h>
 #include <linux/irq_work.h>
+#include <linux/kasan.h>
 #include <linux/llist.h>
 #include <linux/rcupdate_wait.h>
 #include <linux/sched.h>
@@ -1530,6 +1531,10 @@ static void __call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 {
 	if (WARN_ON_ONCE(ssp->srcu_reader_flavor == SRCU_READ_FLAVOR_ATOMIC))
 		return; // Leak the callback rather than corrupt SRCU state.
+
+	/* Record the caller: the irq_work's stack says nothing about it. */
+	kasan_record_aux_stack(rhp);
+
 	if (should_rcu_defer()) {
 		struct srcu_defer *sndp = this_cpu_ptr(&srcu_defer);
 		struct srcu_data *sdp;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/9] srcutiny: Record callback registration stack for KASAN
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
  2026-10-23 10:18 ` [PATCH 1/9] srcu: Record callback registration stack for KASAN Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 3/9] rcu: Record callback registration stack for Tiny RCU Kunwu Chan
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Record the callback registration stack in call_srcu()
for KASAN diagnostics involving Tiny SRCU callbacks.

Suggested-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/srcutiny.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
index 63a3f0a8bc53..3ee28885b96f 100644
--- a/kernel/rcu/srcutiny.c
+++ b/kernel/rcu/srcutiny.c
@@ -10,6 +10,7 @@
 
 #include <linux/export.h>
 #include <linux/irq_work.h>
+#include <linux/kasan.h>
 #include <linux/llist.h>
 #include <linux/mutex.h>
 #include <linux/preempt.h>
@@ -290,6 +291,9 @@ EXPORT_SYMBOL_GPL(srcu_defer_drain);
 void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 	       rcu_callback_t func)
 {
+	/* Record the caller: the irq_work's stack says nothing about it. */
+	kasan_record_aux_stack(rhp);
+
 	if (should_rcu_defer()) {
 		/* A re-entrant call_srcu() during the drain would livelock it. */
 		if (READ_ONCE(srcu_defer_draining) && !in_nmi()) {
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/9] rcu: Record callback registration stack for Tiny RCU
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
  2026-10-23 10:18 ` [PATCH 1/9] srcu: Record callback registration stack for KASAN Kunwu Chan
  2026-10-23 10:18 ` [PATCH 2/9] srcutiny: " Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 4/9] srcu: Validate callback arguments Kunwu Chan
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Record the callback registration stack in call_rcu()
for KASAN diagnostics involving Tiny RCU callbacks.

Suggested-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/tiny.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index 656b6a682e31..bd22fa43108d 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -12,6 +12,7 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/irq_work.h>
+#include <linux/kasan.h>
 #include <linux/llist.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate_wait.h>
@@ -251,6 +252,9 @@ EXPORT_SYMBOL_GPL(synchronize_rcu);
  */
 void call_rcu(struct rcu_head *head, rcu_callback_t func)
 {
+	/* 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);
 		return;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/9] srcu: Validate callback arguments
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (2 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 3/9] rcu: Record callback registration stack for Tiny RCU Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 5/9] rcu: Validate callback arguments in Tiny RCU Kunwu Chan
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Check callback-head alignment and reject NULL callback
functions in the SRCU callback registration paths.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/srcutiny.c | 7 +++++++
 kernel/rcu/srcutree.c | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
index 3ee28885b96f..98864977bed2 100644
--- a/kernel/rcu/srcutiny.c
+++ b/kernel/rcu/srcutiny.c
@@ -291,6 +291,13 @@ EXPORT_SYMBOL_GPL(srcu_defer_drain);
 void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 	       rcu_callback_t func)
 {
+	/* Misaligned rcu_head! */
+	WARN_ON_ONCE((unsigned long)rhp & (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(rhp);
 
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index 46fe2f0cef85..1993ddbdb828 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -1529,6 +1529,13 @@ static void srcu_do_enqueue(struct srcu_struct *ssp, struct rcu_head *rhp,
 static void __call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 			rcu_callback_t func, bool do_norm)
 {
+	/* Misaligned rcu_head! */
+	WARN_ON_ONCE((unsigned long)rhp & (sizeof(void *) - 1));
+
+	/* Avoid NULL dereference if callback is NULL. */
+	if (WARN_ON_ONCE(!func))
+		return;
+
 	if (WARN_ON_ONCE(ssp->srcu_reader_flavor == SRCU_READ_FLAVOR_ATOMIC))
 		return; // Leak the callback rather than corrupt SRCU state.
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/9] rcu: Validate callback arguments in Tiny RCU
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (3 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 4/9] srcu: Validate callback arguments Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 6/9] rcu-tasks: Validate callback arguments Kunwu Chan
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Check callback-head alignment and reject NULL callback
functions in Tiny RCU's call_rcu() path.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/tiny.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index bd22fa43108d..ef0b0474f207 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -252,6 +252,13 @@ EXPORT_SYMBOL_GPL(synchronize_rcu);
  */
 void call_rcu(struct rcu_head *head, rcu_callback_t func)
 {
+	/* 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);
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/9] rcu-tasks: Validate callback arguments
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (4 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 5/9] rcu: Validate callback arguments in Tiny RCU Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 7/9] srcu: Detect duplicate callback enqueue at registration Kunwu Chan
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Check callback-head alignment and reject NULL callback
functions in the generic RCU Tasks callback registration path.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/tasks.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
index fcac7361ec51..5d7f234795b4 100644
--- a/kernel/rcu/tasks.h
+++ b/kernel/rcu/tasks.h
@@ -351,6 +351,13 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
 	bool needwake;
 	struct rcu_tasks_percpu *rtpcp;
 
+	/* Misaligned rcu_head! */
+	WARN_ON_ONCE((unsigned long)rhp & (sizeof(void *) - 1));
+
+	/* Avoid NULL dereference if callback is NULL. */
+	if (WARN_ON_ONCE(!func))
+		return;
+
 	rhp->next = NULL;
 	rhp->func = func;
 	local_irq_save(flags);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/9] srcu: Detect duplicate callback enqueue at registration
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (5 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 6/9] rcu-tasks: Validate callback arguments Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 8/9] srcutiny: Detect duplicate callback enqueue Kunwu Chan
  2026-10-23 10:18 ` [PATCH 9/9] rcu-tasks: " Kunwu Chan
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Move the duplicate-callback check from srcu_do_enqueue() to
__call_srcu() entry so that detected duplicate registrations
are rejected before they reach the deferred-list enqueue path.
Report the callback address, function symbol, and object
information, rate-limited to the first three occurrences.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/srcutree.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index 1993ddbdb828..3838d9fdf532 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -27,6 +27,7 @@
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/srcu.h>
 
@@ -1511,12 +1512,6 @@ static unsigned long srcu_gp_start_if_needed(struct srcu_struct *ssp,
 static void srcu_do_enqueue(struct srcu_struct *ssp, struct rcu_head *rhp,
 			    rcu_callback_t func, bool do_norm)
 {
-	if (debug_rcu_head_queue(rhp)) {
-		/* Probable double call_srcu(), so leak the callback. */
-		WRITE_ONCE(rhp->func, srcu_leak_callback);
-		WARN_ONCE(1, "call_srcu(): Leaked duplicate callback\n");
-		return;
-	}
 	rhp->func = func;
 	(void)srcu_gp_start_if_needed(ssp, rhp, do_norm);
 }
@@ -1529,6 +1524,8 @@ static void srcu_do_enqueue(struct srcu_struct *ssp, struct rcu_head *rhp,
 static void __call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 			rcu_callback_t func, bool do_norm)
 {
+	static atomic_t doublefrees;
+
 	/* Misaligned rcu_head! */
 	WARN_ON_ONCE((unsigned long)rhp & (sizeof(void *) - 1));
 
@@ -1539,6 +1536,16 @@ static void __call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 	if (WARN_ON_ONCE(ssp->srcu_reader_flavor == SRCU_READ_FLAVOR_ATOMIC))
 		return; // Leak the callback rather than corrupt SRCU state.
 
+	if (debug_rcu_head_queue(rhp)) {
+		if (atomic_inc_return(&doublefrees) < 4) {
+			pr_err("%s(): Duplicate call_srcu() CB %p->%pS()\n",
+			       __func__, rhp, rhp->func);
+			mem_dump_obj(rhp);
+		}
+		WRITE_ONCE(rhp->func, srcu_leak_callback);
+		return;
+	}
+
 	/* Record the caller: the irq_work's stack says nothing about it. */
 	kasan_record_aux_stack(rhp);
 
@@ -1554,6 +1561,7 @@ static void __call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 		if (READ_ONCE(sndp->draining) && !in_nmi()) {
 			WARN_ONCE(IS_ENABLED(CONFIG_PROVE_RCU),
 				  "call_srcu() re-entered during callback drain; leaking callback\n");
+			debug_rcu_head_unqueue(rhp);
 			return;
 		}
 		sdp = this_cpu_ptr(ssp->sda);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 8/9] srcutiny: Detect duplicate callback enqueue
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (6 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 7/9] srcu: Detect duplicate callback enqueue at registration Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  2026-10-23 10:18 ` [PATCH 9/9] rcu-tasks: " Kunwu Chan
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Detect duplicate callback enqueue attempts at call_srcu()
entry, before the deferred list can be corrupted.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/srcutiny.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
index 98864977bed2..4400fd2b41b7 100644
--- a/kernel/rcu/srcutiny.c
+++ b/kernel/rcu/srcutiny.c
@@ -12,6 +12,7 @@
 #include <linux/irq_work.h>
 #include <linux/kasan.h>
 #include <linux/llist.h>
+#include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/preempt.h>
 #include <linux/rcupdate_wait.h>
@@ -178,6 +179,7 @@ void srcu_drive_gp(struct work_struct *wp)
 	while (lh) {
 		rhp = lh;
 		lh = lh->next;
+		debug_rcu_head_unqueue(rhp);
 		debug_rcu_head_callback(rhp);
 		local_bh_disable();
 		rhp->func(rhp);
@@ -235,6 +237,8 @@ static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
  * Also called by __srcu_defer_drain() to re-issue a deferred callback, so it
  * must not re-check the deferral condition.
  */
+static void srcu_leak_callback(struct rcu_head *rhp) { }
+
 static void srcu_do_enqueue(struct srcu_struct *ssp, struct rcu_head *rhp,
 			    rcu_callback_t func)
 {
@@ -272,6 +276,8 @@ static void __srcu_defer_drain(struct srcu_struct *ssp)
 	llist_for_each_safe(node, next, llist_del_all(&ssp->defer_cbs)) {
 		struct rcu_head *rhp = (struct rcu_head *)node;
 
+		/* Bounds a node self-linked by a double call_srcu(). */
+		rhp->next = NULL;
 		srcu_do_enqueue(ssp, rhp, rhp->func);
 	}
 	local_irq_restore(flags);
@@ -291,6 +297,8 @@ EXPORT_SYMBOL_GPL(srcu_defer_drain);
 void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 	       rcu_callback_t func)
 {
+	static atomic_t doublefrees;
+
 	/* Misaligned rcu_head! */
 	WARN_ON_ONCE((unsigned long)rhp & (sizeof(void *) - 1));
 
@@ -298,6 +306,16 @@ void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 	if (WARN_ON_ONCE(!func))
 		return;
 
+	if (debug_rcu_head_queue(rhp)) {
+		if (atomic_inc_return(&doublefrees) < 4) {
+			pr_err("%s(): Duplicate call_srcu() CB %p->%pS()\n",
+			       __func__, rhp, rhp->func);
+			mem_dump_obj(rhp);
+		}
+		WRITE_ONCE(rhp->func, srcu_leak_callback);
+		return;
+	}
+
 	/* Record the caller: the irq_work's stack says nothing about it. */
 	kasan_record_aux_stack(rhp);
 
@@ -306,6 +324,7 @@ void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp,
 		if (READ_ONCE(srcu_defer_draining) && !in_nmi()) {
 			WARN_ONCE(IS_ENABLED(CONFIG_PROVE_RCU),
 				  "call_srcu() re-entered during callback drain; leaking callback\n");
+			debug_rcu_head_unqueue(rhp);
 			return;
 		}
 		rhp->func = func;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 9/9] rcu-tasks: Detect duplicate callback enqueue
  2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
                   ` (7 preceding siblings ...)
  2026-10-23 10:18 ` [PATCH 8/9] srcutiny: Detect duplicate callback enqueue Kunwu Chan
@ 2026-10-23 10:18 ` Kunwu Chan
  8 siblings, 0 replies; 10+ messages in thread
From: Kunwu Chan @ 2026-10-23 10:18 UTC (permalink / raw)
  To: jiangshanlai, paulmck, josh, work, frederic, neeraj.upadhyay,
	joelagnelf, boqun, urezki
  Cc: rostedt, mathieu.desnoyers, qiang.zhang, rcu, linux-kernel,
	Kunwu Chan, Kunwu Chan

Detect duplicate callback enqueue attempts in the generic
RCU Tasks callback registration path.

Signed-off-by: Kunwu Chan <chentao@kylinos.cn>
---
 kernel/rcu/tasks.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
index 5d7f234795b4..49b716feb31d 100644
--- a/kernel/rcu/tasks.h
+++ b/kernel/rcu/tasks.h
@@ -6,6 +6,7 @@
  */
 
 #ifdef CONFIG_TASKS_RCU_GENERIC
+#include <linux/mm.h>
 #include "rcu_segcblist.h"
 
 ////////////////////////////////////////////////////////////////////////
@@ -339,9 +340,12 @@ static void call_rcu_tasks_iw_wakeup(struct irq_work *iwp)
 }
 
 // Enqueue a callback for the specified flavor of Tasks RCU.
+static void rcu_tasks_leak_callback(struct rcu_head *rhp) { }
+
 static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
 				   struct rcu_tasks *rtp)
 {
+	static atomic_t doublefrees;
 	int chosen_cpu;
 	unsigned long flags;
 	bool havekthread = smp_load_acquire(&rtp->kthread_ptr);
@@ -358,6 +362,16 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
 	if (WARN_ON_ONCE(!func))
 		return;
 
+	if (debug_rcu_head_queue(rhp)) {
+		if (atomic_inc_return(&doublefrees) < 4) {
+			pr_err("%s(): Duplicate call_rcu_%s() CB %p->%pS()\n",
+			       __func__, rtp->name, rhp, rhp->func);
+			mem_dump_obj(rhp);
+		}
+		WRITE_ONCE(rhp->func, rcu_tasks_leak_callback);
+		return;
+	}
+
 	rhp->next = NULL;
 	rhp->func = func;
 	local_irq_save(flags);
@@ -586,6 +600,7 @@ static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpu
 	raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
 	len = rcl.len;
 	for (rhp = rcu_cblist_dequeue(&rcl); rhp; rhp = rcu_cblist_dequeue(&rcl)) {
+		debug_rcu_head_unqueue(rhp);
 		debug_rcu_head_callback(rhp);
 		local_bh_disable();
 		rhp->func(rhp);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-10-23 10:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 10:18 [PATCH 0/9] rcu: Improve callback diagnostics and validation Kunwu Chan
2026-10-23 10:18 ` [PATCH 1/9] srcu: Record callback registration stack for KASAN Kunwu Chan
2026-10-23 10:18 ` [PATCH 2/9] srcutiny: " Kunwu Chan
2026-10-23 10:18 ` [PATCH 3/9] rcu: Record callback registration stack for Tiny RCU Kunwu Chan
2026-10-23 10:18 ` [PATCH 4/9] srcu: Validate callback arguments Kunwu Chan
2026-10-23 10:18 ` [PATCH 5/9] rcu: Validate callback arguments in Tiny RCU Kunwu Chan
2026-10-23 10:18 ` [PATCH 6/9] rcu-tasks: Validate callback arguments Kunwu Chan
2026-10-23 10:18 ` [PATCH 7/9] srcu: Detect duplicate callback enqueue at registration Kunwu Chan
2026-10-23 10:18 ` [PATCH 8/9] srcutiny: Detect duplicate callback enqueue Kunwu Chan
2026-10-23 10:18 ` [PATCH 9/9] rcu-tasks: " Kunwu Chan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®