]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf header: Add sanity checks to HEADER_BPF_BTF processing
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 10 Apr 2026 22:09:05 +0000 (19:09 -0300)
committerNamhyung Kim <namhyung@kernel.org>
Tue, 14 Apr 2026 06:21:53 +0000 (23:21 -0700)
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@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/header.c

index 705f1ab44bc934861669b52c6e74860a41b4c4fd..f30e48eb3fc32da206cf1e1b84f0a2becd2411a7 100644 (file)
@@ -3622,6 +3622,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) {
@@ -3632,6 +3643,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;