[PATCH 06/28] perf session: Align auxtrace_info priv size before byte-swapping
From: Arnaldo Carvalho de Melo
Date: Sat May 09 2026 - 23:37:19 EST
From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
perf_event__auxtrace_info_swap() passes the raw remainder of
header.size to mem_bswap_64(), which swaps in 8-byte chunks.
If the size is not a multiple of 8, the last iteration reads and
writes 8 bytes from a shorter region, overrunning the event
buffer by up to 7 bytes.
Round down to a u64 boundary — priv[] is a u64 array, so any
unaligned tail is padding that doesn't need swapping.
Also fix swap_sample_id_all() which had the same issue — replace
BUG_ON(size % sizeof(u64)) with rounding down, since crafted
events may have unaligned trailing data.
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@xxxxxxxxxx # Running on a local machine
Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Cc: Ian Rogers <irogers@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@xxxxxxxxxxxxx>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/util/session.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 20b70d6fb7cc8ed4..b55c5168ee9f4aae 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -276,10 +276,16 @@ 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;
+ /* Only swap complete 8-byte elements */
+ size &= ~(int)(sizeof(u64) - 1);
+ if (size > 0)
+ mem_bswap_64(data, size);
}
static void perf_event__all64_swap(union perf_event *event,
@@ -585,6 +591,8 @@ static void perf_event__auxtrace_info_swap(union perf_event *event,
size = event->header.size;
size -= (void *)&event->auxtrace_info.priv - (void *)event;
+ /* priv[] is a u64 array; only swap complete 8-byte elements */
+ size &= ~(size_t)(sizeof(u64) - 1);
mem_bswap_64(event->auxtrace_info.priv, size);
}
--
2.54.0