From: Ian Rogers <irogers@google.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>, Song Liu <song@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org, stable@vger.kernel.org
Subject: [PATCH v1] perf/core: Restore header fields in sideband output callbacks
Date: Mon, 28 Sep 2026 18:42:06 -0700 [thread overview]
Message-ID: <20260929014206.4175245-1-irogers@google.com> (raw)
perf_iterate_sb() invokes its callback for each matching perf_event on
the CPU and task context, passing a shared caller-allocated event
structure.
perf_event_header__init_id() increments header->size by
event->id_header_size. Unlike perf_event_task_output(),
perf_event_comm_output(), perf_event_namespaces_output(),
perf_event_cgroup_output(), perf_event_mmap_output(), and
perf_callchain_deferred_output(), three sideband callbacks failed to
save and restore header.size around perf_event_header__init_id():
- perf_event_ksymbol_output()
- perf_event_bpf_output()
- perf_event_text_poke_output()
When multiple events with attr.ksymbol, attr.bpf_event, or
attr.text_poke and sample_id_all are active on the same CPU, each
subsequent event receives a record whose header.size is inflated by all
preceding events' id_header_size values while only a single id_sample is
written, leaving uninitialized ring-buffer bytes at the end of the
record and causing userspace perf to fail with -EFAULT ("Bad address")
when parsing the sample_id trailer.
Similarly, perf_event_mmap_output() sets PERF_RECORD_MISC_MMAP_BUILD_ID
in mmap_event->event_id.header.misc when event->attr.build_id is
enabled, but only saved and restored header.size and header.type. If an
event with attr.build_id is followed by an event with attr.mmap2 and
!attr.build_id, the second event receives PERF_RECORD_MISC_MMAP_BUILD_ID
in header.misc while its payload contains maj/min/ino/ino_generation
instead of a build ID.
Save and restore header.size in the ksymbol, bpf, and text_poke output
callbacks, and save and restore header.misc in perf_event_mmap_output().
Fixes: 76193a94522f ("perf, bpf: Introduce PERF_RECORD_KSYMBOL")
Fixes: 6ee52e2a3fe4 ("perf, bpf: Introduce PERF_RECORD_BPF_EVENT")
Fixes: e17d43b93e54 ("perf: Add perf text poke event")
Fixes: 88a16a130933 ("perf: Add build id data in mmap2 event")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
kernel/events/core.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 33210aff3ee6..ea3697295bd4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9029,6 +9029,11 @@ static void perf_iterate_sb_cpu(perf_iterate_f output, void *data)
*
* For new callers; ensure that account_pmu_sb_event() includes
* your event, otherwise it might not get delivered.
+ *
+ * Note: @data is shared across all @output calls, so any fields modified
+ * incrementally or conditionally (e.g. header.size via
+ * perf_event_header__init_id()) must be saved and restored by @output,
+ * or unconditionally re-initialized on each call.
*/
static void
perf_iterate_sb(perf_iterate_f output, void *data,
@@ -9723,6 +9728,7 @@ static void perf_event_mmap_output(struct perf_event *event,
struct perf_sample_data sample;
int size = mmap_event->event_id.header.size;
u32 type = mmap_event->event_id.header.type;
+ u16 misc = mmap_event->event_id.header.misc;
bool use_build_id;
int ret;
@@ -9780,6 +9786,7 @@ static void perf_event_mmap_output(struct perf_event *event,
out:
mmap_event->event_id.header.size = size;
mmap_event->event_id.header.type = type;
+ mmap_event->event_id.header.misc = misc;
}
static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
@@ -10244,6 +10251,7 @@ static void perf_event_ksymbol_output(struct perf_event *event, void *data)
struct perf_ksymbol_event *ksymbol_event = data;
struct perf_output_handle handle;
struct perf_sample_data sample;
+ u16 header_size = ksymbol_event->event_id.header.size;
int ret;
if (!perf_event_ksymbol_match(event))
@@ -10254,13 +10262,15 @@ static void perf_event_ksymbol_output(struct perf_event *event, void *data)
ret = perf_output_begin(&handle, &sample, event,
ksymbol_event->event_id.header.size);
if (ret)
- return;
+ goto out;
perf_output_put(&handle, ksymbol_event->event_id);
__output_copy(&handle, ksymbol_event->name, ksymbol_event->name_len);
perf_event__output_id_sample(event, &handle, &sample);
perf_output_end(&handle);
+out:
+ ksymbol_event->event_id.header.size = header_size;
}
void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len, bool unregister,
@@ -10334,6 +10344,7 @@ static void perf_event_bpf_output(struct perf_event *event, void *data)
struct perf_bpf_event *bpf_event = data;
struct perf_output_handle handle;
struct perf_sample_data sample;
+ u16 header_size = bpf_event->event_id.header.size;
int ret;
if (!perf_event_bpf_match(event))
@@ -10344,12 +10355,14 @@ static void perf_event_bpf_output(struct perf_event *event, void *data)
ret = perf_output_begin(&handle, &sample, event,
bpf_event->event_id.header.size);
if (ret)
- return;
+ goto out;
perf_output_put(&handle, bpf_event->event_id);
perf_event__output_id_sample(event, &handle, &sample);
perf_output_end(&handle);
+out:
+ bpf_event->event_id.header.size = header_size;
}
static void perf_event_bpf_emit_ksymbols(struct bpf_prog *prog,
@@ -10496,6 +10509,7 @@ static void perf_event_text_poke_output(struct perf_event *event, void *data)
struct perf_text_poke_event *text_poke_event = data;
struct perf_output_handle handle;
struct perf_sample_data sample;
+ u16 header_size = text_poke_event->event_id.header.size;
u64 padding = 0;
int ret;
@@ -10507,7 +10521,7 @@ static void perf_event_text_poke_output(struct perf_event *event, void *data)
ret = perf_output_begin(&handle, &sample, event,
text_poke_event->event_id.header.size);
if (ret)
- return;
+ goto out;
perf_output_put(&handle, text_poke_event->event_id);
perf_output_put(&handle, text_poke_event->old_len);
@@ -10522,6 +10536,8 @@ static void perf_event_text_poke_output(struct perf_event *event, void *data)
perf_event__output_id_sample(event, &handle, &sample);
perf_output_end(&handle);
+out:
+ text_poke_event->event_id.header.size = header_size;
}
void perf_event_text_poke(const void *addr, const void *old_bytes,
--
2.56.0.rc1.315.gc6ed9934b7-goog
reply other threads:[~2026-09-29 1:42 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260929014206.4175245-1-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--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=song@kernel.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®