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

From: Ian Rogers

Date: Mon Jul 20 2026 - 18:54:42 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 068323b9510d..fb4f736f64c0 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -2447,13 +2447,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))
@@ -2473,16 +2478,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