[PATCH v4 4/4] perf synthetic-events: Fix bounds and union member access in mmap2 build_id synthesis

From: Ian Rogers

Date: Tue Jul 21 2026 - 15:39:33 EST


Fix a critical logic bug in perf_event__synthesize_mmap2_build_id() where
the wrong union member structure size and offset boundaries were utilized.
Safely calculate the exact maximum allowed filename length to guarantee
absolute stack and alignment boundaries for ID sample trailers, preventing
-E2BIG overruns on very long filenames while meeting strict standard C
compliance.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/synthetic-events.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index e547874b77b2..06a960e8ba85 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -2448,13 +2448,18 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,
size_t filename_len = strlen(filename);
size_t ev_len;
u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0;
- void *array;
+ void *array = &ev;
int ret;
+ size_t max_filename_len;

- if (filename_len >= sizeof(ev.mmap2.filename))
- return -EINVAL;
+ max_filename_len = sizeof(ev) -
+ (MAX_ID_HDR_ENTRIES * sizeof(__u64)) -
+ offsetof(struct perf_record_mmap2, filename) - 1;

- ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + filename_len + 1;
+ if (filename_len > max_filename_len)
+ filename_len = max_filename_len;
+
+ ev_len = offsetof(struct perf_record_mmap2, filename) + filename_len + 1;
ev_len = PERF_ALIGN(ev_len, sizeof(u64));

if (ev_len + MAX_ID_HDR_ENTRIES * sizeof(__u64) > sizeof(ev))
@@ -2474,16 +2479,15 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool,

ev.mmap2.build_id_size = bid->size;
if (ev.mmap2.build_id_size > sizeof(ev.mmap2.build_id))
- ev.build_id.size = sizeof(ev.mmap2.build_id);
+ ev.mmap2.build_id_size = sizeof(ev.mmap2.build_id);
memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size);

ev.mmap2.prot = prot;
ev.mmap2.flags = flags;

- memcpy(ev.mmap2.filename, filename, min(strlen(filename), sizeof(ev.mmap.filename)));
+ strlcpy(ev.mmap2.filename, filename, filename_len + 1);

- array = &ev;
- array += ev.header.size;
+ array = (void *)((char *)&ev + ev.header.size);
ret = perf_event__synthesize_id_sample(array, sample_type, sample);
if (ret < 0)
return ret;
--
2.55.0.229.g6434b31f56-goog