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:claude-opus-4.6-1m
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2026-05-02 13:01:34 -03:00
parent fe84caf425
commit 315c81b4b9

View File

@ -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,