perf synthetic-events: Fix bounds and union member access in mmap2 build_id synthesis

Modify bounds and union member access in mmap2 build_id synthesis. Bound
max_filename_len against the minimum of filename array capacity and the
outer union stack layout minus sample ID trailers. This prevents both
-E2BIG overruns and _FORTIFY_SOURCE array bounds aborts on strlcpy even
if the enclosing union expands.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers 2026-07-21 16:52:54 -07:00 committed by Namhyung Kim
parent b97c535768
commit 006a6f0f6e

View File

@ -2457,13 +2457,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 = min(sizeof(ev.mmap2.filename) - 1,
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))
@ -2483,16 +2488,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;