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

From: Ian Rogers

Date: Mon Jul 20 2026 - 13:56:20 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 and clamp maximum filename length to guarantee absolute
stack boundary protections for ID sample trailers, and remove void-pointer
arithmetic to meet strict standard C compliance.

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

diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index aab958cb3bc5..cb5b659822f5 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -2441,13 +2441,16 @@ 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.mmap2.filename) - (MAX_ID_HDR_ENTRIES * sizeof(__u64));

- 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))
@@ -2467,16 +2470,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