]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf cs-etm: Validate num_cpu before metadata allocation
authorArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 13 Jun 2026 17:16:45 +0000 (14:16 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 17 Jun 2026 12:21:03 +0000 (09:21 -0300)
cs_etm__process_auxtrace_info_full() reads num_cpu from untrusted
perf.data and uses it to allocate the metadata pointer array:

  metadata = zalloc(sizeof(*metadata) * num_cpu);

On 32-bit, sizeof(*metadata) is 4, so num_cpu = 0x40000000 overflows
the multiplication to 0, causing zalloc(0) to return a valid zero-sized
allocation followed by out-of-bounds writes in the population loop.

Fix by computing priv_size early and using it to bound num_cpu: each
CPU needs at least one u64 metadata entry, so num_cpu cannot exceed
the total number of u64 entries in the event's private data area.

Fixes: cd8bfd8c973eaff8 ("perf tools: Add processing of coresight metadata")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: James Clark <james.clark@arm.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Tor Jeremiassen <tor@ti.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cs-etm.c

index 0927b0b9c06b15046afeafe23fe170b8248cfcc6..d121c8f22028d5bac6767ec0514d9e22f46262b1 100644 (file)
@@ -3431,6 +3431,18 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
        /* First the global part */
        ptr = (u64 *) auxtrace_info->priv;
        num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
+
+       /*
+        * Bound num_cpu by the event size: the global header consumes
+        * CS_ETM_HEADER_SIZE bytes, and each CPU needs at least one u64
+        * metadata entry after that.
+        */
+       priv_size = total_size - event_header_size - INFO_HEADER_SIZE -
+                   CS_ETM_HEADER_SIZE;
+       if (num_cpu <= 0 || priv_size <= 0 ||
+           num_cpu > priv_size / (int)sizeof(u64))
+               return -EINVAL;
+
        metadata = zalloc(sizeof(*metadata) * num_cpu);
        if (!metadata)
                return -ENOMEM;