From: Ilya Leoshkevich <iii@linux.ibm.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Ilya Leoshkevich <iii@linux.ibm.com>
Subject: [PATCH 1/5] perf jitdump: Fix PID namespace detection
Date: Wed, 5 Nov 2025 20:10:24 +0100 [thread overview]
Message-ID: <20251105191626.34998-2-iii@linux.ibm.com> (raw)
In-Reply-To: <20251105191626.34998-1-iii@linux.ibm.com>
perf inject fails to detect jitdump file produced by a process
running in a different PID namespace if this process has not exited
yet.
The PID namespace heuristic in jit_detect() compares two PIDs:
* pid: outermost NStgid of mmap(jitdump) caller from perf's PoV.
* nsinfo__nstgid(nsi): innermost NStgid of mmap(jitdump) caller from
perf's PoV.
The semantics of the in_pidns variable can be seen in, e.g.,
nsinfo__get_nspid(): it's true if and only if perf and the profiled
process are in different PID namespaces.
The current logic is clearly inverted: if pid and nsinfo__nstgid(nsi)
are different, then the profiled process must be in a different PID
namespace. This, of course, ignores that fact that they may end up
being equal by accident, but that's not the point here.
Fix by flipping the comparison.
Changing just that, however, breaks the case when the process has
exited. Add explicit support for that by adding "synthesized" field to
nsinfo, which tracks whether NStgid was obtained from a running
process (ignoring considerations of PID reuse or running inject on
a different machine). When the namespace information is synthesized,
assume the process ran in a different PID namespace.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
tools/perf/util/jitdump.c | 27 +++++++++++++++++++++------
tools/perf/util/namespaces.c | 9 +++++++++
tools/perf/util/namespaces.h | 2 ++
3 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index b062b1f234b62..19e4bc139935b 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -788,15 +788,30 @@ jit_detect(const char *mmap_name, pid_t pid, struct nsinfo *nsi, bool *in_pidns)
if (!end)
return -1;
- *in_pidns = pid == nsinfo__nstgid(nsi);
/*
- * pid does not match mmap pid
- * pid==0 in system-wide mode (synthesized)
+ * Determine whether the process ran inside a container, and whether it
+ * mapped jit.dump for profiling purposes or by accident. Record this
+ * for further use in jit_inject(). The kernel does not provide PID
+ * namespace information, so we have to resort to guesswork.
*
- * If the pid in the file name is equal to the nstgid, then
- * the agent ran inside a container and perf outside the
- * container, so record it for further use in jit_inject().
+ * If the process exited and perf had to synthesize the namespace
+ * information, then it's not possible to have any certainty; be
+ * aggressive and assume that the process ran inside a container. This
+ * allows the user to proceed with injection at the cost of a small
+ * probability of injecting irrelevant data.
+ *
+ * If the process' NStgid as observed by perf is different from its
+ * innermost NStgid, then it must have run inside a container. There is
+ * a very small probability that NStgids randomly happenned to be the
+ * same; ignore it.
+ *
+ * pid == 0 means system-wide mode, just proceed.
+ *
+ * Finally, the most straightforward case: if the PID in the file name
+ * is equal to the process' NStgid as observed by perf, then it must be
+ * a match.
*/
+ *in_pidns = nsinfo__synthesized(nsi) || pid != nsinfo__nstgid(nsi);
if (pid && !(pid2 == pid || *in_pidns))
return -1;
/*
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 01502570b32d0..7de5d62e271c4 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -132,6 +132,8 @@ int nsinfo__init(struct nsinfo *nsi)
rv = nsinfo__get_nspid(&RC_CHK_ACCESS(nsi)->tgid, &RC_CHK_ACCESS(nsi)->nstgid,
&RC_CHK_ACCESS(nsi)->in_pidns, spath);
+ if (rv == 0)
+ RC_CHK_ACCESS(nsi)->synthesized = false;
out:
free(newns);
@@ -166,6 +168,7 @@ struct nsinfo *nsinfo__new(pid_t pid)
RC_CHK_ACCESS(nsi)->nstgid = pid;
nsinfo__clear_need_setns(nsi);
RC_CHK_ACCESS(nsi)->in_pidns = false;
+ RC_CHK_ACCESS(nsi)->synthesized = true;
/* Init may fail if the process exits while we're trying to look at its
* proc information. In that case, save the pid but don't try to enter
* the namespace.
@@ -197,6 +200,7 @@ struct nsinfo *nsinfo__copy(const struct nsinfo *nsi)
RC_CHK_ACCESS(nnsi)->nstgid = nsinfo__nstgid(nsi);
RC_CHK_ACCESS(nnsi)->need_setns = nsinfo__need_setns(nsi);
RC_CHK_ACCESS(nnsi)->in_pidns = nsinfo__in_pidns(nsi);
+ RC_CHK_ACCESS(nnsi)->synthesized = nsinfo__synthesized(nsi);
if (nsinfo__mntns_path(nsi)) {
RC_CHK_ACCESS(nnsi)->mntns_path = strdup(nsinfo__mntns_path(nsi));
if (!RC_CHK_ACCESS(nnsi)->mntns_path) {
@@ -275,6 +279,11 @@ void nsinfo__set_in_pidns(struct nsinfo *nsi)
RC_CHK_ACCESS(nsi)->in_pidns = true;
}
+bool nsinfo__synthesized(const struct nsinfo *nsi)
+{
+ return RC_CHK_ACCESS(nsi)->synthesized;
+}
+
void nsinfo__mountns_enter(struct nsinfo *nsi,
struct nscookie *nc)
{
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index e95c79b80e27c..41ba2ea8137e5 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -38,6 +38,7 @@ DECLARE_RC_STRUCT(nsinfo) {
bool in_pidns;
char *mntns_path;
refcount_t refcnt;
+ bool synthesized;
};
struct nscookie {
@@ -60,6 +61,7 @@ pid_t nsinfo__nstgid(const struct nsinfo *nsi);
pid_t nsinfo__pid(const struct nsinfo *nsi);
bool nsinfo__in_pidns(const struct nsinfo *nsi);
void nsinfo__set_in_pidns(struct nsinfo *nsi);
+bool nsinfo__synthesized(const struct nsinfo *nsi);
void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
void nsinfo__mountns_exit(struct nscookie *nc);
--
2.51.1
next prev parent reply other threads:[~2025-11-05 19:16 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-05 19:10 [PATCH 0/5] perf jitdump: Fix PID namespace detection Ilya Leoshkevich
2025-11-05 19:10 ` Ilya Leoshkevich [this message]
2025-11-07 2:16 ` [PATCH 1/5] " Namhyung Kim
2025-11-07 8:19 ` Ilya Leoshkevich
2025-11-14 8:07 ` Namhyung Kim
2025-11-14 12:44 ` Ilya Leoshkevich
2025-11-14 18:44 ` Namhyung Kim
2025-11-05 19:10 ` [PATCH 2/5] perf test java symbol: Get rid of shellcheck warnings Ilya Leoshkevich
2025-11-07 2:07 ` Namhyung Kim
2025-11-07 7:57 ` Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 3/5] perf test java symbol: Extract LIBJVMTI detection Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 4/5] perf test java symbol: Fix a false negative in symbol regex Ilya Leoshkevich
2025-11-07 2:08 ` Namhyung Kim
2025-11-07 7:59 ` Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 5/5] perf test java symbol: Add PID namespace variant Ilya Leoshkevich
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=20251105191626.34998-2-iii@linux.ibm.com \
--to=iii@linux.ibm.com \
--cc=acme@kernel.org \
--cc=agordeev@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.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