[PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing

From: Arnaldo Carvalho de Melo

Date: Thu Apr 09 2026 - 20:44:25 EST


From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

Validate the BTF entry count and individual data sizes when reading
HEADER_BPF_BTF from perf.data files to prevent excessive memory
allocation from malformed files.

Reuses the MAX_BPF_PROGS (131072) and MAX_BPF_DATA_LEN (256 MB)
limits from HEADER_BPF_PROG_INFO processing.

Cc: Song Liu <song@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Ian Rogers <irogers@xxxxxxxxxx>
Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/util/header.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 628d091658c8c40e..f47b040b76292c81 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3619,6 +3619,17 @@ static int process_bpf_btf(struct feat_fd *ff __maybe_unused, void *data __mayb
if (do_read_u32(ff, &count))
return -1;

+ if (count > MAX_BPF_PROGS) {
+ pr_err("bpf btf count %u too large (max %u)\n", count, MAX_BPF_PROGS);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + count * 2 * sizeof(u32)) {
+ pr_err("Invalid HEADER_BPF_BTF: section too small (%zu) for %u entries\n",
+ ff->size, count);
+ return -1;
+ }
+
down_write(&env->bpf_progs.lock);

for (i = 0; i < count; ++i) {
@@ -3629,6 +3640,12 @@ static int process_bpf_btf(struct feat_fd *ff __maybe_unused, void *data __mayb
if (do_read_u32(ff, &data_size))
goto out;

+ if (data_size > MAX_BPF_DATA_LEN) {
+ pr_err("bpf btf data size %u too large (max %u)\n",
+ data_size, MAX_BPF_DATA_LEN);
+ goto out;
+ }
+
node = malloc(sizeof(struct btf_node) + data_size);
if (!node)
goto out;
--
2.53.0