* [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