* [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; 22+ 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] 22+ 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; 22+ 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] 22+ 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 1:08 ` sashiko-bot
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, 1 reply; 22+ 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] 22+ 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; 22+ 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] 22+ 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 1:14 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
` (8 subsequent siblings)
12 siblings, 1 reply; 22+ 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] 22+ 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 1:04 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
` (7 subsequent siblings)
12 siblings, 1 reply; 22+ 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] 22+ 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 1:04 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
` (6 subsequent siblings)
12 siblings, 1 reply; 22+ 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] 22+ 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 1:10 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 08/13] perf header: Sanity check HEADER_GROUP_DESC Arnaldo Carvalho de Melo
` (5 subsequent siblings)
12 siblings, 1 reply; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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:58 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 11/13] perf header: Sanity check HEADER_PMU_CAPS Arnaldo Carvalho de Melo
` (2 subsequent siblings)
12 siblings, 1 reply; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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
2026-04-10 1:30 ` sashiko-bot
12 siblings, 1 reply; 22+ 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] 22+ messages in thread
* Re: [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY
2026-04-10 0:39 ` [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 0:58 ` sashiko-bot
2026-04-10 1:01 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 0:58 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [Low] The MAX_PMU_MAPPINGS macro is defined locally inside process_pmu_mappings() but reused in process_hybrid_topology().
--
commit b5af27fec41475de3166cc72abe94ddc329689cc
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Sanity check HEADER_HYBRID_TOPOLOGY
This commit adds an upper bound check on nr_nodes in
process_hybrid_topology() to harden against malformed perf.data files by
reusing the MAX_PMU_MAPPINGS limit.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> --- 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) {
This isn't a bug, but could this cause build failures if the functions are
reordered in the future?
MAX_PMU_MAPPINGS is currently defined locally inside process_pmu_mappings():
tools/perf/util/header.c:process_pmu_mappings() {
...
#define MAX_PMU_MAPPINGS 4096
if (pmu_num > MAX_PMU_MAPPINGS) {
...
}
While the C preprocessor doesn't respect function block scope, allowing it
to be used here, this relies on process_pmu_mappings() always appearing
lexically before process_hybrid_topology() in this file.
Should this macro be hoisted to file scope to prevent accidental breakage
during future refactoring?
> + pr_err("Invalid HEADER_HYBRID_TOPOLOGY: nr_nodes (%u) > %u\n",
> + nr, MAX_PMU_MAPPINGS);
> + return -1;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=10
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/13] perf header: Sanity check HEADER_HYBRID_TOPOLOGY
2026-04-10 0:58 ` sashiko-bot
@ 2026-04-10 1:01 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 22+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-04-10 1:01 UTC (permalink / raw)
To: sashiko; +Cc: linux-perf-users
On Fri, Apr 10, 2026 at 12:58:37AM +0000, sashiko-bot@kernel.org wrote:
> Sashiko AI review found 1 potential issue(s):
> - [Low] The MAX_PMU_MAPPINGS macro is defined locally inside process_pmu_mappings() but reused in process_hybrid_topology().
> --
>
> commit b5af27fec41475de3166cc72abe94ddc329689cc
> Author: Arnaldo Carvalho de Melo <acme@redhat.com>
>
> perf header: Sanity check HEADER_HYBRID_TOPOLOGY
>
> This commit adds an upper bound check on nr_nodes in
> process_hybrid_topology() to harden against malformed perf.data files by
> reusing the MAX_PMU_MAPPINGS limit.
>
> > diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> > --- 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) {
>
> This isn't a bug, but could this cause build failures if the functions are
> reordered in the future?
>
> MAX_PMU_MAPPINGS is currently defined locally inside process_pmu_mappings():
>
> tools/perf/util/header.c:process_pmu_mappings() {
> ...
> #define MAX_PMU_MAPPINGS 4096
> if (pmu_num > MAX_PMU_MAPPINGS) {
> ...
> }
>
> While the C preprocessor doesn't respect function block scope, allowing it
> to be used here, this relies on process_pmu_mappings() always appearing
> lexically before process_hybrid_topology() in this file.
>
> Should this macro be hoisted to file scope to prevent accidental breakage
> during future refactoring?
Yeah, I'll do it in v2.
- Arnaldo
> > + pr_err("Invalid HEADER_HYBRID_TOPOLOGY: nr_nodes (%u) > %u\n",
> > + nr, MAX_PMU_MAPPINGS);
> > + return -1;
> > + }
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=10
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 1:04 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:04 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 3 potential issue(s):
- [Critical] Integer truncation in `do_read_bitmap` leads to a severe heap buffer overflow when reading malformed `perf.data` files.
- [Medium] The newly introduced minimum section size check mathematically undercalculates the minimum required bytes per node.
- [Low] `MAX_NUMA_NODES` macro used for validation is structurally brittle as it is defined inside the body of another function.
--
commit e1c73bb8da303b10ce33d83b53452c1195efcf94
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Sanity check HEADER_MEM_TOPOLOGY
This patch adds validation to process_mem_topology() to harden against
malformed perf.data files. It introduces an upper bound check on nr_nodes
using MAX_NUMA_NODES and a minimum section size check before allocating
memory.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 2c6f7c96e2dcc..45f533fbb8fdc 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) {
Is it safe to reuse MAX_NUMA_NODES here?
It appears to be defined inside the body of process_numa_topology() earlier
in the file. If the file is ever refactored or process_numa_topology() is
conditionally compiled out, could this break the compilation of
process_mem_topology()?
> + 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)) {
Does this check mathematically undercalculate the minimum required bytes per
node?
The formula assumes that each memory node consumes exactly 2 u64 fields
(node and size). However, do_read_bitmap() unconditionally reads an
additional u64 size field from the file before any bitmap data is processed:
tools/perf/util/header.c:do_read_bitmap() {
...
ret = do_read_u64(ff, &size);
...
}
Should the absolute minimum size required per node actually be 3 u64s
(24 bytes) to prevent structurally undersized sections from passing the
initial size validation?
> + pr_err("Invalid HEADER_MEM_TOPOLOGY: section too small (%zu) for %llu nodes\n",
> + ff->size, (unsigned long long)nr);
> + return -1;
> + }
Since this patch hardens against malformed files, could the truncation in
do_read_bitmap() overflow the set allocation?
In do_read_bitmap(), a 64-bit size is read from the file and passed to
bitmap_zalloc():
tools/perf/util/header.c:do_read_bitmap() {
...
ret = do_read_u64(ff, &size);
if (ret)
return ret;
set = bitmap_zalloc(size);
...
}
Because bitmap_zalloc() takes a 32-bit signed integer, an
attacker-controlled size exceeding INT_MAX (e.g., 0x100000040ULL) would be
implicitly truncated, resulting in a tiny allocation.
However, the subsequent loop uses the original, untruncated 64-bit value to
bound its execution:
for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
ret = do_read_u64(ff, p + i);
...
}
Could this read millions of 64-bit words directly from the untrusted file
into the undersized set allocation?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=6
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 1:04 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:04 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [Low] The minimum section size calculation under-calculates the required bytes per node by omitting the string length field.
--
commit 39d7a2e6e6f3028c87af277c0da0635894776c8f
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Sanity check HEADER_NUMA_TOPOLOGY
This commit adds validation to process_numa_topology to harden against
malformed perf.data files. It adds an upper bound check on nr_nodes and
verifies the minimum section size before allocating the nodes array.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> --- 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 (ff->size < sizeof(u32) + nr * (sizeof(u32) + 2 * sizeof(u64))) {
Does this minimum section size calculation under-count the required bytes
per node?
The validation check calculates the minimum payload size as 20 bytes per
node for the node, mem_total, and mem_free fields. However, the subsequent
loop also reads a string for each node via do_read_string().
Since do_read_string() internally reads a mandatory 4-byte string length
field first, does the actual minimum size per node need to account for
those additional 4 bytes?
> + pr_err("Invalid HEADER_NUMA_TOPOLOGY: section too small (%zu) for %u nodes\n",
> + ff->size, nr);
> + return -1;
> + }
> +
> nodes = calloc(nr, sizeof(*nodes));
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=5
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 02/13] perf header: Bump up the max number of command line args allowed
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 1:08 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:08 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [High] Heap buffer overflow in `process_cmdline` due to unbounded file reads into an undersized allocation.
--
commit 3f19c967de1b22045b10b4bbef5f04c6e3827352
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Bump up the max number of command line args allowed
This commit increases the upper limit validation for command line
arguments from 32,768 to 1,048,576 to accommodate large wildcard expansions.
Link: https://sashiko.dev/#/patchset/20260408172846.96360-1-acme%40kernel.org
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index a2796b72adc4d..22c44b6f0b098 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
While this patch doesn't introduce the underlying issue, does bumping
this limit exacerbate a regression involving a heap buffer overflow in
process_cmdline?
Currently, process_cmdline allocates the buffer based on ff->size:
cmdline = zalloc(ff->size + nr + 1);
When parsing directly from the file descriptor, do_read_string uses
__do_read_fd, which reads lengths and string data from the file without
capping the total bytes read to ff->size.
If a maliciously crafted perf.data file provides a small ff->size but
supplies arbitrarily large strings in the payload, could do_read_string
read them successfully, causing the subsequent memcpy loop to overflow
the cmdline allocation?
Additionally, since do_read_string lacks null-termination enforcement,
if a string is provided without a null byte, could strlen perform an
out-of-bounds heap over-read, further inflating the length of the string
being copied?
> static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)
> {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=2
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
@ 2026-04-10 1:10 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:10 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 2 potential issue(s):
- [High] Incomplete Hardening / Brittle State Mutation leading to NULL Pointer Dereference
- [High] Information Leak / Out-of-Bounds Read in `do_read_string()`
--
commit f8a3a1de8d8a986abb3e1819cdf6e18f8f1d826d
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Sanity check HEADER_PMU_MAPPINGS
Add upper bound check on pmu_num in process_pmu_mappings() to harden
against malformed perf.data files (max 4096).
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 45f533fbb8fdc..1d7ca467acf32 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;
This isn't a regression introduced by this patch, but since the goal is to
harden process_pmu_mappings() against malformed files, does this leave a crash
condition if parsing fails later?
If an error occurs after env->nr_pmu_mappings is set:
while (pmu_num) {
if (do_read_u32(ff, &type))
goto error;
name = do_read_string(ff);
if (!name)
goto error;
the function jumps to the error label and returns -1.
If the caller perf_session__read_header() ignores the error, we are left with
env->nr_pmu_mappings > 0 but env->pmu_mappings as NULL.
Could this lead to a NULL pointer dereference in functions like
perf_env__has_pmu_mapping() that iterate up to env->nr_pmu_mappings and pass
env->pmu_mappings directly to strtoul()? Should env->nr_pmu_mappings only be
updated on the success path?
This is also not a regression introduced by this patch, but does
do_read_string() ensure the returned string is null-terminated?
if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
goto error;
If a malformed perf.data file provides a string without a null terminator,
and do_read_string() returns a buffer that isn't null-terminated, could the
%s format specifier in strbuf_addf() read past the end of the allocation
until it hits a null byte in adjacent heap memory?
Could this lead to an out-of-bounds heap read, potentially crashing perf or
leaking heap data into the PMU mappings output?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=7
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY
2026-04-10 0:39 ` [PATCH 04/13] perf header: Sanity check HEADER_CPU_TOPOLOGY Arnaldo Carvalho de Melo
@ 2026-04-10 1:14 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [High] The patch introduces a deterministic NULL pointer dereference crash on malformed inputs by incorrectly freeing `env->cpu`. The author changed `return -1;` to `goto free_cpu;` (which calls `zfree(&env->cpu)`) under the mistaken assumption that `env->cpu` was leaking.
--
commit 725d6d7d1ccd2df010084b584d9517330e1864ac
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Sanity check HEADER_CPU_TOPOLOGY
This commit adds bounds checking for sibling counts against available
CPUs in the CPU topology header and attempts to prevent a perceived
leak of the env->cpu array on error paths.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 2d23dbc666b67..a7df8ed9a69e9 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
[ ... ]
> @@ -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;
> + }
> +
[ ... ]
> error:
> strbuf_release(&sb);
> zfree(&str);
> free_cpu:
> zfree(&env->cpu);
> return -1;
> }
Does this zfree() cause a NULL pointer dereference regression on malformed
inputs?
When a parsing error occurs, env->cpu is freed and set to NULL. However,
perf_session__read_header() ignores the error returned by
perf_header__process_sections() and proceeds with the session.
If the session continues, tools like perf stat will later call functions
such as perf_env__get_socket_aggr_by_cpu(), which unconditionally
dereferences env->cpu[cpu.cpu].socket_id.
Was env->cpu actually leaking before this change? It appears to be safely
cleaned up during teardown by perf_env__exit() even if an error is
encountered here.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=4
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing
2026-04-10 0:40 ` [PATCH 13/13] perf header: Add sanity checks to HEADER_BPF_BTF processing Arnaldo Carvalho de Melo
@ 2026-04-10 1:30 ` sashiko-bot
0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-04-10 1:30 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [Low] Brittle dependency on macros defined in another function's scope.
--
commit 2ef335810a8ef7ba04bf003c542540f62231696e
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf header: Add sanity checks to HEADER_BPF_BTF processing
This commit adds bounds checking for BTF entry counts and data sizes
when reading HEADER_BPF_BTF from perf.data files to prevent excessive
memory allocations.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> --- 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;
> + }
This isn't a bug, but is it safe to rely on MAX_BPF_PROGS and
MAX_BPF_DATA_LEN being available here?
Looking at tools/perf/util/header.c, both of these macros are defined locally
inside the body of process_bpf_prog_info(), which happens to precede this
function in the file:
static int process_bpf_prog_info(...)
{
...
#define MAX_BPF_PROGS 131072
...
#define MAX_BPF_DATA_LEN (256 * 1024 * 1024)
...
}
While the C preprocessor allows this since process_bpf_prog_info() is
evaluated first, would it make sense to move these macro definitions to
the file scope or a shared header? This would prevent hidden dependencies
and compilation failures if these functions are ever reordered.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260410004000.148138-1-acme@kernel.org?part=13
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-04-10 1:30 UTC | newest]
Thread overview: 22+ 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 1:08 ` sashiko-bot
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 1:14 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 05/13] perf header: Sanity check HEADER_NUMA_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 1:04 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 06/13] perf header: Sanity check HEADER_MEM_TOPOLOGY Arnaldo Carvalho de Melo
2026-04-10 1:04 ` sashiko-bot
2026-04-10 0:39 ` [PATCH 07/13] perf header: Sanity check HEADER_PMU_MAPPINGS Arnaldo Carvalho de Melo
2026-04-10 1:10 ` sashiko-bot
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:58 ` sashiko-bot
2026-04-10 1:01 ` 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
2026-04-10 1:30 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox