From: Mark Amirkan via B4 Relay <devnull+markdamirkan.gmail.com@kernel.org>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
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>
Cc: Mark Amirkan <markdamirkan@gmail.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH v2 2/2] perf evsel: Validate RAW sample before byte swapping
Date: Thu, 03 Sep 2026 04:04:21 -0700 [thread overview]
Message-ID: <20260903-sympwn-linux-002-final-v2-v2-2-0aee1fca1f95@gmail.com> (raw)
In-Reply-To: <20260903-sympwn-linux-002-final-v2-v2-0-0aee1fca1f95@gmail.com>
From: Mark Amirkan <markdamirkan@gmail.com>
For an opposite-endian RAW sample, __evsel__parse_sample() passes the
input-controlled size to mem_bswap_64() before checking whether the
payload fits in the event. A truncated record can therefore make the helper
read and write past the event boundary.
A crafted perf.data file makes perf report crash with SIGSEGV. ASan
reports the out-of-bounds access. A regression test puts backed data past
the declared end and shows that it is changed before the parser returns
-EFAULT.
Move the bounds checks before mem_bswap_64(). Check the rounded length too,
because the helper accesses complete 64-bit words. Complete records are
handled as before.
Fixes: f9d8adb345d7 ("perf evsel: Fix swap for samples with raw data")
Cc: stable@vger.kernel.org
Assisted-by: Symbolic
Signed-off-by: Mark Amirkan <markdamirkan@gmail.com>
---
tools/perf/tests/sample-parsing.c | 61 +++++++++++++++++++++++++++++++++++++++
tools/perf/util/evsel.c | 17 ++++++-----
2 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 583951534937..bd30f6d4c31b 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -461,6 +461,55 @@ static int test_truncated_branch_stack(void)
return 0;
}
+static int test_truncated_swapped_raw(u16 event_size, u32 raw_size)
+{
+ struct perf_event_attr attr = {
+ .sample_type = PERF_SAMPLE_RAW,
+ };
+ struct {
+ struct perf_event_header header;
+ union {
+ u64 value;
+ u32 words[2];
+ } raw;
+ u64 canary;
+ } input = {
+ .header = {
+ .type = PERF_RECORD_SAMPLE,
+ .size = event_size,
+ },
+ /* Parsing a pre-swapped word exchanges these two u32 values. */
+ .raw.words = { 0x12345678, raw_size },
+ .canary = 0x8877665544332211ULL,
+ };
+ struct perf_sample sample;
+ struct evsel *evsel;
+ u64 raw = input.raw.value;
+ u64 canary = input.canary;
+ int err;
+
+ evsel = evsel__new(&attr);
+ if (!evsel)
+ return -1;
+
+ evsel->sample_size = __evsel__sample_size(attr.sample_type);
+ err = __evsel__parse_sample(evsel, (union perf_event *)&input,
+ &sample, /*needs_swap=*/true);
+ perf_sample__exit(&sample);
+ evsel__put(evsel);
+
+ if (err != -EFAULT) {
+ pr_debug("truncated swapped RAW sample (size %u, raw %u) returned %d, expected -EFAULT\n",
+ event_size, raw_size, err);
+ return -1;
+ }
+ if (input.raw.value != raw || input.canary != canary) {
+ pr_debug("truncated swapped RAW sample modified data before validation\n");
+ return -1;
+ }
+ return 0;
+}
+
/**
* test__sample_parsing - test sample parsing.
*
@@ -481,6 +530,18 @@ static int test__sample_parsing(struct test_suite *test __maybe_unused, int subt
if (err)
return err;
+ /* The declared RAW payload extends past an otherwise aligned event. */
+ err = test_truncated_swapped_raw(sizeof(struct perf_event_header) +
+ sizeof(u64), 16);
+ if (err)
+ return err;
+
+ /* The final complete word touched by mem_bswap_64() extends past it. */
+ err = test_truncated_swapped_raw(sizeof(struct perf_event_header) +
+ sizeof(u32) + 9, 9);
+ if (err)
+ return err;
+
/*
* Fail the test if it has not been updated when new sample format bits
* were added. Please actually update the test rather than just change
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index cc0bc0857754..ce429eb247b6 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -3584,7 +3584,10 @@ int __evsel__parse_sample(struct evsel *evsel, union perf_event *event,
}
if (type & PERF_SAMPLE_RAW) {
+ const __u64 *raw;
+
OVERFLOW_CHECK_u64(array);
+ raw = array;
u.val64 = *array;
/*
@@ -3600,16 +3603,14 @@ int __evsel__parse_sample(struct evsel *evsel, union perf_event *event,
}
data->raw_size = u.val32[0];
- /*
- * The raw data is aligned on 64bits including the
- * u32 size, so it's safe to use mem_bswap_64.
- */
- if (swapped)
- mem_bswap_64((void *) array, data->raw_size);
-
array = (void *)array + sizeof(u32);
-
OVERFLOW_CHECK(array, data->raw_size, max_size);
+ if (swapped) {
+ /* mem_bswap_64() accesses complete 64-bit words. */
+ sz = roundup((u64)data->raw_size, sizeof(u64));
+ OVERFLOW_CHECK(raw, sz, max_size);
+ mem_bswap_64((void *)raw, data->raw_size);
+ }
data->raw_data = (void *)array;
array = (void *)array + data->raw_size;
}
--
Git-146)
next prev parent reply other threads:[~2026-09-03 11:05 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 11:04 [PATCH v2 0/2] perf evsel: Validate cross-endian samples before byte swapping Mark Amirkan via B4 Relay
2026-09-03 11:04 ` [PATCH v2 1/2] perf evsel: Validate branch stack " Mark Amirkan via B4 Relay
2026-09-03 11:20 ` sashiko-bot
2026-09-03 11:04 ` Mark Amirkan via B4 Relay [this message]
2026-09-03 11:23 ` [PATCH v2 2/2] perf evsel: Validate RAW sample " sashiko-bot
2026-09-03 20:19 ` [PATCH v2 0/2] perf evsel: Validate cross-endian samples " Ian Rogers
2026-09-05 0:32 ` Arnaldo Carvalho de Melo
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=20260903-sympwn-linux-002-final-v2-v2-2-0aee1fca1f95@gmail.com \
--to=devnull+markdamirkan.gmail.com@kernel.org \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--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=markdamirkan@gmail.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