aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
authorArnaldo Carvalho de Melo <acme@redhat.com>2026-05-02 13:01:34 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-05-29 11:44:31 -0300
commit28a753d24eb915ff953ea01cb0f1b502206fe1d0 (patch)
treeb6e2788c6af31ead214c7da02cfb4791d125f0df /tools
parent0dcd3a131c8acd9e6aa62ec408af64cd9292d9ff (diff)
downloadlinux-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.c14
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,