diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-05-02 13:01:34 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-05-29 11:44:31 -0300 |
| commit | 28a753d24eb915ff953ea01cb0f1b502206fe1d0 (patch) | |
| tree | b6e2788c6af31ead214c7da02cfb4791d125f0df /tools | |
| parent | 0dcd3a131c8acd9e6aa62ec408af64cd9292d9ff (diff) | |
| download | linux-next-history-28a753d24eb915ff953ea01cb0f1b502206fe1d0.tar.gz | |
perf session: Fix swap_sample_id_all() crash on crafted events
swap_sample_id_all() calls BUG_ON(size % sizeof(u64)) which kills
perf on any event where the sample_id_all tail is not 8-byte aligned.
A crafted perf.data can trigger this trivially.
Replace BUG_ON with a bounds check: skip the swap if the data pointer
is past the end of the event, and only swap when there are bytes
remaining.
Note: the strlen calls in string-field swap handlers (comm,
mmap, mmap2, cgroup) are replaced with bounded strnlen by the
next patch in this series ("perf session: Add validated swap
infrastructure with null-termination checks").
Reported-by: sashiko-bot@kernel.org # Running on a local machine
Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/session.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 24f2ba599b807..37544a3574185 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -276,10 +276,18 @@ void perf_session__delete(struct perf_session *session) static void swap_sample_id_all(union perf_event *event, void *data) { void *end = (void *) event + event->header.size; - int size = end - data; + int size; - BUG_ON(size % sizeof(u64)); - mem_bswap_64(data, size); + if (data >= end) + return; + + size = end - data; + if (size % sizeof(u64)) { + pr_warning("swap_sample_id_all: unaligned sample_id_all remainder (%d), skipping swap\n", size); + return; + } + if (size > 0) + mem_bswap_64(data, size); } static void perf_event__all64_swap(union perf_event *event, |
