* [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers
@ 2026-04-10 0:39 Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 01/13] perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
Hi,
Sashiko recently mentioned the lack of sanity checking headers
in perf.data files, that with a fuzzy or maliciously crafted file could
make processing a perf.data file cause deleterious results.
Add sanity checks and some arbitrarily generous upper limits to
headers, if some are found to be questionable, lets tweak them in
upcoming versions of this patchset.
As registered in the Assisted-by tags in the patches, this was
done using Claude code to speed up development, hopefully no
hallucinations are present.
I'm also trying to get some of these checks into review-prompts
skills, some of which were already merged, for instance:
https://github.com/masoncl/review-prompts/commit/2bb2159893ea926e120105416e95629b9ef1508c
Thanks,
- Arnaldo
Arnaldo Carvalho de Melo (13):
perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO
perf header: Bump up the max number of command line args allowed
perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO
perf header: Sanity check HEADER_CPU_TOPOLOGY
perf header: Sanity check HEADER_NUMA_TOPOLOGY
perf header: Sanity check HEADER_MEM_TOPOLOGY
perf header: Sanity check HEADER_PMU_MAPPINGS
perf header: Sanity check HEADER_GROUP_DESC
perf header: Sanity check HEADER_CACHE
perf header: Sanity check HEADER_HYBRID_TOPOLOGY
perf header: Sanity check HEADER_PMU_CAPS
perf header: Sanity check HEADER_BPF_PROG_INFO
perf header: Add sanity checks to HEADER_BPF_BTF processing
tools/perf/util/header.c | 219 +++++++++++++++++++++++++++++++++++++--
1 file changed, 213 insertions(+), 6 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/13] perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 02/13] perf header: Bump up the max number of command line args allowed Arnaldo Carvalho de Melo
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Further validate the HEADER_CPU_DOMAIN_INFO fields, this time checking
the nr_domains field.
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 6 ++++++
1 file changed, 6 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c6efddb70aee2904..a2796b72adc4d908 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3731,6 +3731,12 @@ static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused
if (do_read_u32(ff, &nr_domains))
return -1;
+ if (nr_domains > max_sched_domains) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: nr_domains %u > max_sched_domains (%u)\n",
+ nr_domains, max_sched_domains);
+ return -1;
+ }
+
cd_map[cpu]->nr_domains = nr_domains;
cd_map[cpu]->domains = calloc(max_sched_domains, sizeof(*d_info));
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 02/13] perf header: Bump up the max number of command line args allowed
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 01/13] perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 03/13] perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
We need to do some upper limit validation, bump up the arbitrary limit
as per suggestion of Sashiko about command line wildcard expansion
ending up with more than 32768 args.
Link: https://sashiko.dev/#/patchset/20260408172846.96360-1-acme%40kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a2796b72adc4d908..22c44b6f0b098f95 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2795,8 +2795,11 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
return 0;
}
-// Some reasonable arbitrary max for the number of command line arguments
-#define MAX_CMDLINE_NR 32768
+/*
+ * Some arbitrary max for the number of command line arguments,
+ * Wildcards can expand and end up with tons of command line args.
+ */
+#define MAX_CMDLINE_NR 1048576
static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/13] perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 01/13] perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 02/13] perf header: Bump up the max number of command line args allowed Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY Arnaldo Carvalho de Melo
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo, Swapnil Sapkal
From: Arnaldo Carvalho de Melo <acme@redhat.com>
While working on some cleanups sashiko questioned about pre-existing
issues, namely lacking sanity checks for perf.data headers, add some
with the help of Claude.
Cc: Ian Rogers <irogers@google.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 44 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 22c44b6f0b098f95..2d23dbc666b676be 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2722,6 +2722,13 @@ static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)
ret = do_read_u32(ff, &nr_cpus_online);
if (ret)
return ret;
+
+ if (nr_cpus_online > nr_cpus_avail) {
+ pr_err("Invalid HEADER_NRCPUS: nr_cpus_online (%u) > nr_cpus_avail (%u)\n",
+ nr_cpus_online, nr_cpus_avail);
+ return -1;
+ }
+
env->nr_cpus_avail = (int)nr_cpus_avail;
env->nr_cpus_online = (int)nr_cpus_online;
return 0;
@@ -3698,6 +3705,17 @@ static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused
nra = env->nr_cpus_avail;
nr = env->nr_cpus_online;
+ if (nra == 0 || nr == 0) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: missing HEADER_NRCPUS\n");
+ return -1;
+ }
+
+ if (ff->size < 2 * sizeof(u32) + nr * 2 * sizeof(u32)) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: section too small (%zu) for %u CPUs\n",
+ (size_t)ff->size, nr);
+ return -1;
+ }
+
cd_map = calloc(nra, sizeof(*cd_map));
if (!cd_map)
return -1;
@@ -3714,6 +3732,19 @@ static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused
if (ret)
return ret;
+ /*
+ * Sanity check: real systems have at most ~10 sched domain levels
+ * (SMT, CLS, MC, PKG + NUMA hops). Reject obviously bogus values
+ * from malformed perf.data files before they cause excessive
+ * allocation in the per-CPU loop.
+ */
+#define MAX_SCHED_DOMAINS 64
+ if (max_sched_domains > MAX_SCHED_DOMAINS) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: max_sched_domains %u > %u\n",
+ max_sched_domains, MAX_SCHED_DOMAINS);
+ return -1;
+ }
+
env->max_sched_domains = max_sched_domains;
for (i = 0; i < nr; i++) {
@@ -3725,6 +3756,11 @@ static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused
return -1;
}
+ if (cd_map[cpu]) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: duplicate cpu %u\n", cpu);
+ return -1;
+ }
+
cd_map[cpu] = zalloc(sizeof(*cd_map[cpu]));
if (!cd_map[cpu])
return -1;
@@ -3760,7 +3796,13 @@ static int process_cpu_domain_info(struct feat_fd *ff, void *data __maybe_unused
if (!d_info)
return -1;
- assert(cd_map[cpu]->domains[domain] == NULL);
+ if (cd_map[cpu]->domains[domain]) {
+ pr_err("Invalid HEADER_CPU_DOMAIN_INFO: duplicate domain %u for cpu %u\n",
+ domain, cpu);
+ free(d_info);
+ return -1;
+ }
+
cd_map[cpu]->domains[domain] = d_info;
d_info->domain = domain;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (2 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 03/13] perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add validation to process_cpu_topology() to harden against malformed
perf.data files:
- Verify nr_cpus_avail was initialized (HEADER_NRCPUS processed first)
- Bounds check sibling counts (cores, threads, dies) against nr_cpus_avail
- Fix two bare 'return -1' that leaked env->cpu by using 'goto free_cpu'
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2d23dbc666b676be..a7df8ed9a69e9231 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2859,6 +2859,11 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
int cpu_nr = env->nr_cpus_avail;
u64 size = 0;
+ if (cpu_nr == 0) {
+ pr_err("Invalid HEADER_CPU_TOPOLOGY: missing HEADER_NRCPUS\n");
+ return -1;
+ }
+
env->cpu = calloc(cpu_nr, sizeof(*env->cpu));
if (!env->cpu)
return -1;
@@ -2866,6 +2871,12 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
if (do_read_u32(ff, &nr))
goto free_cpu;
+ if (nr > (u32)cpu_nr) {
+ pr_err("Invalid HEADER_CPU_TOPOLOGY: nr_sibling_cores (%u) > nr_cpus_avail (%d)\n",
+ nr, cpu_nr);
+ goto free_cpu;
+ }
+
env->nr_sibling_cores = nr;
size += sizeof(u32);
if (strbuf_init(&sb, 128) < 0)
@@ -2885,7 +2896,13 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
env->sibling_cores = strbuf_detach(&sb, NULL);
if (do_read_u32(ff, &nr))
- return -1;
+ goto free_cpu;
+
+ if (nr > (u32)cpu_nr) {
+ pr_err("Invalid HEADER_CPU_TOPOLOGY: nr_sibling_threads (%u) > nr_cpus_avail (%d)\n",
+ nr, cpu_nr);
+ goto free_cpu;
+ }
env->nr_sibling_threads = nr;
size += sizeof(u32);
@@ -2934,7 +2951,13 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
return 0;
if (do_read_u32(ff, &nr))
- return -1;
+ goto free_cpu;
+
+ if (nr > (u32)cpu_nr) {
+ pr_err("Invalid HEADER_CPU_TOPOLOGY: nr_sibling_dies (%u) > nr_cpus_avail (%d)\n",
+ nr, cpu_nr);
+ goto free_cpu;
+ }
env->nr_sibling_dies = nr;
size += sizeof(u32);
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (3 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add validation to process_numa_topology() to harden against malformed
perf.data files:
- Upper bound check on nr_nodes (max 4096)
- Minimum section size check before allocating
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 13 +++++++++++++
1 file changed, 13 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a7df8ed9a69e9231..2c6f7c96e2dccaf1 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3003,6 +3003,19 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
if (do_read_u32(ff, &nr))
return -1;
+#define MAX_NUMA_NODES 4096
+ if (nr > MAX_NUMA_NODES) {
+ pr_err("Invalid HEADER_NUMA_TOPOLOGY: nr_nodes (%u) > %u\n",
+ nr, MAX_NUMA_NODES);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + nr * (sizeof(u32) + 2 * sizeof(u64))) {
+ pr_err("Invalid HEADER_NUMA_TOPOLOGY: section too small (%zu) for %u nodes\n",
+ ff->size, nr);
+ return -1;
+ }
+
nodes = calloc(nr, sizeof(*nodes));
if (!nodes)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (4 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add validation to process_mem_topology() to harden against malformed
perf.data files:
- Upper bound check on nr_nodes (reuses MAX_NUMA_NODES, 4096)
- Minimum section size check before allocating
This is particularly important here since nr is u64, making unbounded
values especially dangerous.
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 12 ++++++++++++
1 file changed, 12 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2c6f7c96e2dccaf1..45f533fbb8fdc3c6 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3306,6 +3306,18 @@ static int process_mem_topology(struct feat_fd *ff,
if (do_read_u64(ff, &nr))
return -1;
+ if (nr > MAX_NUMA_NODES) {
+ pr_err("Invalid HEADER_MEM_TOPOLOGY: nr_nodes (%llu) > %u\n",
+ (unsigned long long)nr, MAX_NUMA_NODES);
+ return -1;
+ }
+
+ if (ff->size < 3 * sizeof(u64) + nr * 2 * sizeof(u64)) {
+ pr_err("Invalid HEADER_MEM_TOPOLOGY: section too small (%zu) for %llu nodes\n",
+ ff->size, (unsigned long long)nr);
+ return -1;
+ }
+
nodes = calloc(nr, sizeof(*nodes));
if (!nodes)
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (5 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 08/13] perf header: Sanity check HEADER_GROUP_DESC Arnaldo Carvalho de Melo
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add upper bound check on pmu_num in process_pmu_mappings() to harden
against malformed perf.data files (max 4096).
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 13 +++++++++++++
1 file changed, 13 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 45f533fbb8fdc3c6..1d7ca467acf32bd4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3067,6 +3067,19 @@ static int process_pmu_mappings(struct feat_fd *ff, void *data __maybe_unused)
return 0;
}
+#define MAX_PMU_MAPPINGS 4096
+ if (pmu_num > MAX_PMU_MAPPINGS) {
+ pr_err("Invalid HEADER_PMU_MAPPINGS: pmu_num (%u) > %u\n",
+ pmu_num, MAX_PMU_MAPPINGS);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + pmu_num * 2 * sizeof(u32)) {
+ pr_err("Invalid HEADER_PMU_MAPPINGS: section too small (%zu) for %u PMUs\n",
+ ff->size, pmu_num);
+ return -1;
+ }
+
env->nr_pmu_mappings = pmu_num;
if (strbuf_init(&sb, 128) < 0)
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/13] perf header: Sanity check HEADER_GROUP_DESC
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (6 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 09/13] perf header: Sanity check HEADER_CACHE Arnaldo Carvalho de Melo
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add upper bound check on nr_groups in process_group_desc() to harden
against malformed perf.data files (max 32768), and move the env
assignment after validation.
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1d7ca467acf32bd4..8e3f4655fbacc6dd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3130,12 +3130,26 @@ static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
if (do_read_u32(ff, &nr_groups))
return -1;
- env->nr_groups = nr_groups;
if (!nr_groups) {
pr_debug("group desc not available\n");
return 0;
}
+#define MAX_GROUP_DESC 32768
+ if (nr_groups > MAX_GROUP_DESC) {
+ pr_err("Invalid HEADER_GROUP_DESC: nr_groups (%u) > %u\n",
+ nr_groups, MAX_GROUP_DESC);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + nr_groups * 3 * sizeof(u32)) {
+ pr_err("Invalid HEADER_GROUP_DESC: section too small (%zu) for %u groups\n",
+ ff->size, nr_groups);
+ return -1;
+ }
+
+ env->nr_groups = nr_groups;
+
desc = calloc(nr_groups, sizeof(*desc));
if (!desc)
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/13] perf header: Sanity check HEADER_CACHE
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (7 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 08/13] perf header: Sanity check HEADER_GROUP_DESC Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY Arnaldo Carvalho de Melo
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add upper bound check on cache entry count in process_cache() to harden
against malformed perf.data files (max 32768).
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 13 +++++++++++++
1 file changed, 13 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8e3f4655fbacc6dd..494206faeb250956 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3241,6 +3241,19 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
if (do_read_u32(ff, &cnt))
return -1;
+#define MAX_CACHE_ENTRIES 32768
+ if (cnt > MAX_CACHE_ENTRIES) {
+ pr_err("Invalid HEADER_CACHE: cnt (%u) > %u\n",
+ cnt, MAX_CACHE_ENTRIES);
+ return -1;
+ }
+
+ if (ff->size < 2 * sizeof(u32) + cnt * 7 * sizeof(u32)) {
+ pr_err("Invalid HEADER_CACHE: section too small (%zu) for %u entries\n",
+ ff->size, cnt);
+ return -1;
+ }
+
caches = calloc(cnt, sizeof(*caches));
if (!caches)
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (8 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 09/13] perf header: Sanity check HEADER_CACHE Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 11/13] perf header: Sanity check HEADER_PMU_CAPS Arnaldo Carvalho de Melo
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add upper bound check on nr_nodes in process_hybrid_topology() to
harden against malformed perf.data files (reuses MAX_PMU_MAPPINGS,
4096).
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 12 ++++++++++++
1 file changed, 12 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 494206faeb250956..a1f19c1954774e9d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3448,6 +3448,18 @@ static int process_hybrid_topology(struct feat_fd *ff,
if (do_read_u32(ff, &nr))
return -1;
+ if (nr > MAX_PMU_MAPPINGS) {
+ pr_err("Invalid HEADER_HYBRID_TOPOLOGY: nr_nodes (%u) > %u\n",
+ nr, MAX_PMU_MAPPINGS);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + nr * 2 * sizeof(u32)) {
+ pr_err("Invalid HEADER_HYBRID_TOPOLOGY: section too small (%zu) for %u nodes\n",
+ ff->size, nr);
+ return -1;
+ }
+
nodes = calloc(nr, sizeof(*nodes));
if (!nodes)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/13] perf header: Sanity check HEADER_PMU_CAPS
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (9 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 12/13] perf header: Sanity check HEADER_BPF_PROG_INFO Arnaldo Carvalho de Melo
2026-04-10 0:40 ` [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing Arnaldo Carvalho de Melo
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo, Ravi Bangoria
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Add upper bound checks in PMU capabilities processing to harden against
malformed perf.data files:
- nr_pmu bounded to MAX_PMU_MAPPINGS (4096) in process_pmu_caps()
- nr_pmu_caps bounded to MAX_PMU_CAPS (512) in __process_pmu_caps()
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Ian Rogers <irogers@google.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a1f19c1954774e9d..03426132e58dc933 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3675,6 +3675,13 @@ static int __process_pmu_caps(struct feat_fd *ff, int *nr_caps,
if (!nr_pmu_caps)
return 0;
+#define MAX_PMU_CAPS 512
+ if (nr_pmu_caps > MAX_PMU_CAPS) {
+ pr_err("Invalid pmu caps: nr_pmu_caps (%u) > %u\n",
+ nr_pmu_caps, MAX_PMU_CAPS);
+ return -1;
+ }
+
*caps = calloc(nr_pmu_caps, sizeof(char *));
if (!*caps)
return -1;
@@ -3752,6 +3759,18 @@ static int process_pmu_caps(struct feat_fd *ff, void *data __maybe_unused)
return 0;
}
+ if (nr_pmu > MAX_PMU_MAPPINGS) {
+ pr_err("Invalid HEADER_PMU_CAPS: nr_pmu (%u) > %u\n",
+ nr_pmu, MAX_PMU_MAPPINGS);
+ return -1;
+ }
+
+ if (ff->size < sizeof(u32) + nr_pmu * sizeof(u32)) {
+ pr_err("Invalid HEADER_PMU_CAPS: section too small (%zu) for %u PMUs\n",
+ ff->size, nr_pmu);
+ return -1;
+ }
+
pmu_caps = calloc(nr_pmu, sizeof(*pmu_caps));
if (!pmu_caps)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 12/13] perf header: Sanity check HEADER_BPF_PROG_INFO
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (10 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 11/13] perf header: Sanity check HEADER_PMU_CAPS Arnaldo Carvalho de Melo
@ 2026-04-10 0:39 ` Arnaldo Carvalho de Melo
2026-04-10 0:40 ` [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing Arnaldo Carvalho de Melo
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:39 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <acme@redhat.com>
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>
---
| 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 03426132e58dc933..628d091658c8c40e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3522,6 +3522,19 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _
if (do_read_u32(ff, &count))
return -1;
+#define MAX_BPF_PROGS 131072
+ 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) {
@@ -3539,6 +3552,13 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _
goto out;
}
+#define MAX_BPF_DATA_LEN (256 * 1024 * 1024)
+ 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)
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
` (11 preceding siblings ...)
2026-04-10 0:39 ` [PATCH 12/13] perf header: Sanity check HEADER_BPF_PROG_INFO Arnaldo Carvalho de Melo
@ 2026-04-10 0:40 ` Arnaldo Carvalho de Melo
12 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 0:40 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Kan Liang, Clark Williams, linux-kernel,
linux-perf-users, Arnaldo Carvalho de Melo, Song Liu
From: Arnaldo Carvalho de Melo <acme@redhat.com>
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>
---
| 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--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
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-04-10 0:41 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10 0:39 [PATCHES perf-tools-next v1 00/13] Sanity check perf.data headers Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 01/13] perf header: Validate nr_domains when reading HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 02/13] perf header: Bump up the max number of command line args allowed Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 03/13] perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 08/13] perf header: Sanity check HEADER_GROUP_DESC Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 09/13] perf header: Sanity check HEADER_CACHE Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 11/13] perf header: Sanity check HEADER_PMU_CAPS Arnaldo Carvalho de Melo
2026-04-10 0:39 ` [PATCH 12/13] perf header: Sanity check HEADER_BPF_PROG_INFO Arnaldo Carvalho de Melo
2026-04-10 0:40 ` [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox