Commit 22a2e2b2 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Namhyung Kim
Browse files

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 376ce5a9
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -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);