diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-04-10 19:09:04 -0300 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2026-04-13 23:21:53 -0700 |
| commit | 66af7e9b05c4e7ff435c0aef0d253a65d290f03c (patch) | |
| tree | cbf92981daf556757e252db251e5b866ad12e1f1 /tools/perf/util | |
| parent | f5722a6b6a443fd56ce0a71b4be4c75d7a857dbe (diff) | |
perf header: Sanity check HEADER_BPF_PROG_INFO
Add validation to process_bpf_prog_info() to harden against malformed
perf.data files:
- Upper bound on BPF program count (max 131072)
- Upper bound on per-program data_len (max 256MB)
Cc: Ian Rogers <irogers@google.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>
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/header.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 37c1afbc0816..705f1ab44bc9 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -63,6 +63,8 @@ #include <event-parse.h> #endif +#define MAX_BPF_DATA_LEN (256 * 1024 * 1024) +#define MAX_BPF_PROGS 131072 #define MAX_CACHE_ENTRIES 32768 #define MAX_GROUP_DESC 32768 #define MAX_NUMA_NODES 4096 @@ -3525,6 +3527,18 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _ if (do_read_u32(ff, &count)) return -1; + if (count > MAX_BPF_PROGS) { + pr_err("Invalid HEADER_BPF_PROG_INFO: count (%u) > %u\n", + count, MAX_BPF_PROGS); + return -1; + } + + if (ff->size < sizeof(u32) + count * (2 * sizeof(u32) + sizeof(u64))) { + pr_err("Invalid HEADER_BPF_PROG_INFO: 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) { @@ -3542,6 +3556,12 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _ goto out; } + if (data_len > MAX_BPF_DATA_LEN) { + pr_warning("Invalid HEADER_BPF_PROG_INFO: data_len (%u) too large\n", + data_len); + goto out; + } + info_linear = malloc(sizeof(struct perf_bpil) + data_len); if (!info_linear) |
