From: Danish Khateeb <danishkhateeb03@gmail.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Marco Elver <elver@google.com>,
Frederic Weisbecker <frederic@kernel.org>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
Danish Khateeb <danishkhateeb03@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH v2] perf/core: Don't send SIGTRAP after exec removed the event
Date: Wed, 30 Sep 2026 09:42:48 -0500 [thread overview]
Message-ID: <20260930144248.59858-1-danishkhateeb03@gmail.com> (raw)
A sigtrap event must also set remove_on_exec, so that its SIGTRAP never
reaches a program after exec. But the signal is sent from task work,
which only runs on the way back to user space. If the event overflows
shortly before execve(), the task work can still be pending when the
task enters execve(), and then runs when execve() returns. By then
perf_event_exec() has removed the event and the new program has default
signal handlers, so the SIGTRAP kills it.
The exec_stress test in the remove_on_exec selftest catches this and
fails about half the time in a VM. A process that opens a sigtrap event
on itself and then calls execve() is killed by SIGTRAP in 15% to 50% of
runs, both on an AMD machine running v7.2 and in a VM, with or without
close-on-exec on the event fd.
perf_event_exit_event() sets PERF_EVENT_STATE_EXIT when exec removes the
event. If the event fd is close-on-exec and was the last reference to
the file, exec also queues the file release as task work. Task work runs
newest first, so perf_release() runs before the SIGTRAP work and moves
the event on to PERF_EVENT_STATE_DEAD. Exit is already caught by the
PF_EXITING check in perf_sigtrap(). So don't send the signal when the
event state is PERF_EVENT_STATE_EXIT or lower, which means the event has
been removed. That also covers PERF_EVENT_STATE_REVOKED, where the PMU
is gone.
Fixes: 97ba62b27867 ("perf: Add support for SIGTRAP on perf events")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Danish Khateeb <danishkhateeb03@gmail.com>
---
Notes:
Changes in v2:
- Skip the signal for every state at or below PERF_EVENT_STATE_EXIT, not
only EXIT. With a close-on-exec event fd the file release runs first
and moves the event to PERF_EVENT_STATE_DEAD, so v1 still killed 360
of 2000 children. Reported by Sashiko.
- v1: https://lore.kernel.org/all/20260929182935.355892-1-danishkhateeb03@gmail.com/
Tested on v7.3-rc5 x86_64 under virtme-ng (KASAN, lockdep, 8 vCPUs on an
AMD Zen 3 host):
- selftests/perf_events/remove_on_exec: exec_stress failed in 9 of 20
runs before, all 20 pass after.
- The exec_stress pattern in a loop (30 inheriting children, 50 rounds):
a child was killed by SIGTRAP in 17 rounds before, in none after.
- Each child opens its own sigtrap + remove_on_exec event and execs:
756 of 2000 children were killed before, none after. With
PERF_FLAG_FD_CLOEXEC: 836 of 2000 before, 360 with v1, none after.
On the bare-metal host running v7.2.6 the same program kills 297 to
1033 of 2000 children across runs, and 1012 of 2000 with
PERF_FLAG_FD_CLOEXEC.
- sigtrap_threads, watermark_signal and mmap pass before and after. No
new kernel warnings.
v7.2 fails the same way in the VM. I did not test kernels older than
v7.2. gcc W=1 and sparse show no new warnings.
kernel/events/core.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 634d2ccbab82..eabe6cdf7a88 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7631,6 +7631,15 @@ static void perf_sigtrap(struct perf_event *event)
if (current->flags & PF_EXITING)
return;
+ /*
+ * The event was removed after this signal was queued, e.g. by exec()
+ * (remove_on_exec), which may also have closed its fd (close-on-exec).
+ * The new program has default signal handlers, so a SIGTRAP would
+ * kill it.
+ */
+ if (event->state <= PERF_EVENT_STATE_EXIT)
+ return;
+
/*
* We'd expect this to only occur if the irq_work is delayed and either
* ctx->task or current has changed in the meantime. This can be the
base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e
--
2.55.0
next reply other threads:[~2026-09-30 14:42 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 14:42 Danish Khateeb [this message]
2026-09-30 15:16 ` Peter Zijlstra
2026-09-30 15:59 ` Danishk2445
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=20260930144248.59858-1-danishkhateeb03@gmail.com \
--to=danishkhateeb03@gmail.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=elver@google.com \
--cc=frederic@kernel.org \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=stable@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
all inboxes | Powered by JetHome®