diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-04-11 01:08:56 +0300 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2026-04-14 09:21:53 +0300 |
| commit | 22a2e2b29217455cf337c765fc26ad2f55d7291a (patch) | |
| tree | 83ec51531e86dc5fef1f50d8d10f669b5ee8fa4f /tools | |
| parent | 376ce5a9f706a75815c8281861b66060438798d1 (diff) | |
| download | linux-22a2e2b29217455cf337c765fc26ad2f55d7291a.tar.xz | |
perf header: Sanity check HEADER_CPU_TOPOLOGY
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>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/header.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4cb748763c8a..acd6b07528e0 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2861,6 +2861,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; @@ -2868,6 +2873,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) @@ -2887,7 +2898,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); @@ -2936,7 +2953,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); |
