From: Steven Rostedt <rostedt@kernel.org>
To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
bpf@vger.kernel.org, x86@kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Josh Poimboeuf <jpoimboe@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Andrii Nakryiko <andrii@kernel.org>,
Indu Bhagat <indu.bhagat@oracle.com>,
"Jose E. Marchesi" <jemarch@gnu.org>,
Beau Belgrave <beaub@linux.microsoft.com>,
Jens Remus <jremus@linux.ibm.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
Jens Axboe <axboe@kernel.dk>, Florian Weimer <fweimer@redhat.com>,
Sam James <sam@gentoo.org>
Subject: [PATCH v14 07/12] unwind deferred: Add unwind_completed mask to stop spurious callbacks
Date: Wed, 16 Jul 2025 20:49:17 -0400 [thread overview]
Message-ID: <20250717004957.580552530@kernel.org> (raw)
In-Reply-To: 20250717004910.297898999@kernel.org
From: Steven Rostedt <rostedt@goodmis.org>
If there's more than one registered tracer to the unwind deferred
infrastructure, it is currently possible that one tracer could cause extra
callbacks to happen for another tracer if the former requests a deferred
stacktrace after the latter's callback was executed and before the task
went back to user space.
Here's an example of how this could occur:
[Task enters kernel]
tracer 1 request -> add cookie to its buffer
tracer 1 request -> add cookie to its buffer
<..>
[ task work executes ]
tracer 1 callback -> add trace + cookie to its buffer
[tracer 2 requests and triggers the task work again]
[ task work executes again ]
tracer 1 callback -> add trace + cookie to its buffer
tracer 2 callback -> add trace + cookie to its buffer
[Task exits back to user space]
This is because the bit for tracer 1 gets set in the task's unwind_mask
when it did its request and does not get cleared until the task returns
back to user space. But if another tracer were to request another deferred
stacktrace, then the next task work will executed all tracer's callbacks
that have their bits set in the task's unwind_mask.
To fix this issue, add another mask called unwind_completed and place it
into the task's info->cache structure. The cache structure is allocated
on the first occurrence of a deferred stacktrace and this unwind_completed
mask is not needed until then. It's better to have it in the cache than to
permanently waste space in the task_struct.
After a tracer's callback is executed, it's bit gets set in this
unwind_completed mask. When the task_work enters, it will AND the task's
unwind_mask with the inverse of the unwind_completed which will eliminate
any work that already had its callback executed since the task entered the
kernel.
When the task leaves the kernel, it will reset this unwind_completed mask
just like it resets the other values as it enters user space.
Link: https://lore.kernel.org/all/20250716142609.47f0e4a5@batman.local.home/
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
include/linux/unwind_deferred.h | 4 +++-
include/linux/unwind_deferred_types.h | 1 +
kernel/unwind/deferred.c | 19 +++++++++++++++----
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/include/linux/unwind_deferred.h b/include/linux/unwind_deferred.h
index 337ead927d4d..b9ec4c8515c7 100644
--- a/include/linux/unwind_deferred.h
+++ b/include/linux/unwind_deferred.h
@@ -55,8 +55,10 @@ static __always_inline void unwind_reset_info(void)
* depends on nr_entries being cleared on exit to user,
* this needs to be a separate conditional.
*/
- if (unlikely(info->cache))
+ if (unlikely(info->cache)) {
info->cache->nr_entries = 0;
+ info->cache->unwind_completed = 0;
+ }
}
#else /* !CONFIG_UNWIND_USER */
diff --git a/include/linux/unwind_deferred_types.h b/include/linux/unwind_deferred_types.h
index 5dc9cda141ff..33b62ac25c86 100644
--- a/include/linux/unwind_deferred_types.h
+++ b/include/linux/unwind_deferred_types.h
@@ -3,6 +3,7 @@
#define _LINUX_UNWIND_USER_DEFERRED_TYPES_H
struct unwind_cache {
+ unsigned long unwind_completed;
unsigned int nr_entries;
unsigned long entries[];
};
diff --git a/kernel/unwind/deferred.c b/kernel/unwind/deferred.c
index e19f02ef416d..a3d26014a2e6 100644
--- a/kernel/unwind/deferred.c
+++ b/kernel/unwind/deferred.c
@@ -166,12 +166,18 @@ static void unwind_deferred_task_work(struct callback_head *head)
unwind_user_faultable(&trace);
+ if (info->cache)
+ bits &= ~(info->cache->unwind_completed);
+
cookie = info->id.id;
guard(mutex)(&callback_mutex);
list_for_each_entry(work, &callbacks, list) {
- if (test_bit(work->bit, &bits))
+ if (test_bit(work->bit, &bits)) {
work->func(work, &trace, cookie);
+ if (info->cache)
+ info->cache->unwind_completed |= BIT(work->bit);
+ }
}
}
@@ -260,23 +266,28 @@ int unwind_deferred_request(struct unwind_work *work, u64 *cookie)
void unwind_deferred_cancel(struct unwind_work *work)
{
struct task_struct *g, *t;
+ int bit;
if (!work)
return;
+ bit = work->bit;
+
/* No work should be using a reserved bit */
- if (WARN_ON_ONCE(BIT(work->bit) & RESERVED_BITS))
+ if (WARN_ON_ONCE(BIT(bit) & RESERVED_BITS))
return;
guard(mutex)(&callback_mutex);
list_del(&work->list);
- __clear_bit(work->bit, &unwind_mask);
+ __clear_bit(bit, &unwind_mask);
guard(rcu)();
/* Clear this bit from all threads */
for_each_process_thread(g, t) {
- clear_bit(work->bit, &t->unwind_info.unwind_mask);
+ clear_bit(bit, &t->unwind_info.unwind_mask);
+ if (t->unwind_info.cache)
+ clear_bit(bit, &t->unwind_info.cache->unwind_completed);
}
}
--
2.47.2
next prev parent reply other threads:[~2025-07-17 0:49 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-17 0:49 [PATCH v14 00/12] unwind_user: x86: Deferred unwinding infrastructure Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 01/12] unwind_user: Add user space unwinding API with frame pointer support Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 02/12] unwind_user/deferred: Add unwind_user_faultable() Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 03/12] unwind_user/deferred: Add unwind cache Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 04/12] unwind_user/deferred: Add deferred unwinding interface Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 05/12] unwind_user/deferred: Make unwind deferral requests NMI-safe Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 06/12] unwind deferred: Use bitmask to determine which callbacks to call Steven Rostedt
2025-07-17 0:49 ` Steven Rostedt [this message]
2025-07-17 0:49 ` [PATCH v14 08/12] unwind: Add USED bit to only have one conditional on way back to user space Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 09/12] unwind deferred: Use SRCU unwind_deferred_task_work() Steven Rostedt
2025-07-17 4:43 ` Paul E. McKenney
2025-07-17 12:25 ` Steven Rostedt
2025-07-17 15:48 ` Paul E. McKenney
2025-07-17 16:10 ` Steven Rostedt
2025-07-17 16:27 ` Paul E. McKenney
2025-07-17 16:38 ` Steven Rostedt
2025-07-17 16:54 ` Paul E. McKenney
2025-07-17 0:49 ` [PATCH v14 10/12] unwind: Finish up unwind when a task exits Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 11/12] unwind_user/x86: Enable frame pointer unwinding on x86 Steven Rostedt
2025-07-17 0:49 ` [PATCH v14 12/12] unwind deferred/x86: Do not defer stack tracing for compat tasks Steven Rostedt
2025-07-17 0:51 ` [PATCH v14 00/12] unwind_user: x86: Deferred unwinding infrastructure Steven Rostedt
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=20250717004957.580552530@kernel.org \
--to=rostedt@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=axboe@kernel.dk \
--cc=beaub@linux.microsoft.com \
--cc=bpf@vger.kernel.org \
--cc=fweimer@redhat.com \
--cc=indu.bhagat@oracle.com \
--cc=jemarch@gnu.org \
--cc=jolsa@kernel.org \
--cc=jpoimboe@kernel.org \
--cc=jremus@linux.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=sam@gentoo.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=x86@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).