summaryrefslogtreecommitdiff
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2026-06-07 02:57:49 +0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-06-10 17:38:45 +0300
commit5484b43a0ec8231c36fba6ead654cb72dbba8b8f (patch)
tree89e8b1f66f0a22f688123541afaee9199b4a939b /tools/perf
parent7953a3a9b8e02e98c6e6958f291d0ae22393e46a (diff)
downloadlinux-5484b43a0ec8231c36fba6ead654cb72dbba8b8f.tar.xz
perf tools: Use perf_env__get_cpu_topology() in machine__resolve()
machine__resolve() accesses env->cpu[al->cpu].socket_id after checking al->cpu >= 0 and env->cpu != NULL, but without validating al->cpu against env->nr_cpus_avail. Since al->cpu comes from the untrusted perf.data sample, a crafted file with a large CPU index causes an out-of-bounds heap read. Use perf_env__get_cpu_topology() which validates both NULL and bounds. Also bounds-check al->cpu before the cast to struct perf_cpu (int16_t): without this, values like 65536 silently truncate to 0, bypassing the accessor's internal check and returning CPU 0's topology. Fixes: 0c4c4debb0adda4c ("perf tools: Add processor socket info to hist_entry and addr_location") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/event.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 66f4843bb235..ea75816d126a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -14,6 +14,7 @@
#include <linux/perf_event.h>
#include "cpumap.h"
#include "dso.h"
+#include "env.h"
#include "event.h"
#include "debug.h"
#include "hist.h"
@@ -836,8 +837,18 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
if (al->cpu >= 0) {
struct perf_env *env = machine->env;
- if (env && env->cpu)
- al->socket = env->cpu[al->cpu].socket_id;
+ /*
+ * Bounds-check al->cpu (s32) before casting to struct perf_cpu
+ * (int16_t): without this, e.g. 65536 truncates to 0 and silently
+ * returns CPU 0's topology. Can go once perf_cpu.cpu is widened.
+ */
+ if (env && al->cpu < env->nr_cpus_avail) {
+ struct cpu_topology_map *topo;
+
+ topo = perf_env__get_cpu_topology(env, (struct perf_cpu){ al->cpu });
+ if (topo)
+ al->socket = topo->socket_id;
+ }
}
/* Account for possible out-of-order switch events. */