diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-10 21:01:15 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-17 08:28:53 -0300 |
| commit | 10b3c3d63ecc17c6acb855bac5f40367f1115765 (patch) | |
| tree | 954ce136490f63c00488c77f11da6878ff490d1c | |
| parent | 500f5dd0a8b6f7bd174102587c7dff5a7d2fecbf (diff) | |
| download | lwn-10b3c3d63ecc17c6acb855bac5f40367f1115765.tar.gz lwn-10b3c3d63ecc17c6acb855bac5f40367f1115765.zip | |
perf bpf: Validate func_info_rec_size and sub_id in synthesize_bpf_prog_name()
synthesize_bpf_prog_name() computes a pointer into the func_info array
using sub_id * info->func_info_rec_size without validating either value.
Both come from perf.data and are untrusted:
- A func_info_rec_size smaller than sizeof(struct bpf_func_info) means
the finfo pointer would reference a truncated entry, reading past it
into adjacent data.
- A sub_id >= nr_func_info computes an offset past the func_info buffer,
causing an out-of-bounds read.
Add bounds checks for both values before computing the pointer offset.
When validation fails, fall through to the non-BTF name path instead
of reading garbage.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs")
Cc: Song Liu <songliubraving@fb.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/util/bpf-event.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index c4594969d767..fe6fbca508c5 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -143,7 +143,9 @@ static int synthesize_bpf_prog_name(char *buf, int size, name_len = scnprintf(buf, size, "bpf_prog_"); name_len += snprintf_hex(buf + name_len, size - name_len, prog_tags[sub_id], BPF_TAG_SIZE); - if (btf) { + if (btf && + info->func_info_rec_size >= sizeof(*finfo) && + sub_id < info->nr_func_info) { finfo = func_infos + sub_id * info->func_info_rec_size; t = btf__type_by_id(btf, finfo->type_id); if (t) |
