summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2026-04-10 19:09:04 -0300
committerNamhyung Kim <namhyung@kernel.org>2026-04-13 23:21:53 -0700
commit66af7e9b05c4e7ff435c0aef0d253a65d290f03c (patch)
treecbf92981daf556757e252db251e5b866ad12e1f1 /tools/perf/util
parentf5722a6b6a443fd56ce0a71b4be4c75d7a857dbe (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.c20
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)