From: sashiko-bot@kernel.org
To: "Arnaldo Carvalho de Melo" <acme@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH 25/27] perf session: Bound nr_cpus_avail and validate sample CPU
Date: Thu, 21 May 2026 02:43:37 +0000 [thread overview]
Message-ID: <20260521024338.346AE1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260521011027.622268-26-acme@kernel.org>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Clamping env->nr_cpus_avail in process_nrcpus breaks bounds checking in downstream header parsing, causing valid perf.data files from machines with many cores to be rejected.
Pre-existing issues:
- [High] The new CPU bounds check explicitly bypasses clamping if sample.cpu == (u32)-1, allowing out-of-bounds reads in downstream tools (report, diff, sched, script, annotate).
--
commit 02f073a206c5c99ac57b234875b83bcb6a4e3aa5
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
perf session: Bound nr_cpus_avail and validate sample CPU
This commit clamps nr_cpus_avail to MAX_NR_CPUS when reading HEADER_NRCPUS
and applies a bounds check to sample.cpu in perf_session__deliver_event().
It attempts to protect fixed-size arrays in downstream consumers while
preserving the (u32)-1 sentinel value for events without CPU info.
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 8ab05d46021b7..8bc5904591d49 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -2894,12 +2895,36 @@ static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)
[ ... ]
> + /*
> + * FIXME: Several downstream consumers use fixed-size arrays
> + * indexed by CPU (timechart MAX_CPUS, kwork/sched/annotate
> + * DECLARE_BITMAP(MAX_NR_CPUS)). Until these are converted
> + * to dynamic allocation, clamp nr_cpus_avail so per-event
> + * CPU bounds checks reject samples above the array limit.
> + * Data from CPUs beyond MAX_NR_CPUS will be lost.
> + *
> + * Pipe-mode streams from pre-2017 perf or third-party tools
> + * that lack HEADER_NRCPUS will hit the MAX_NR_CPUS fallback
> + * in perf_session__deliver_event() instead.
> + */
> + if (nr_cpus_avail > MAX_NR_CPUS) {
> + pr_warning("WARNING: perf.data recorded on a %u-CPU machine but perf is compiled with MAX_NR_CPUS=%d.\n"
> + " Samples from CPUs >= %d will be clamped to CPU 0. Consider rebuilding\n"
> + " perf with a larger MAX_NR_CPUS, or help convert fixed-size CPU arrays to\n"
> + " dynamic allocation.\n",
> + nr_cpus_avail, MAX_NR_CPUS, MAX_NR_CPUS);
> + nr_cpus_avail = MAX_NR_CPUS;
> + if (nr_cpus_online > nr_cpus_avail)
> + nr_cpus_online = nr_cpus_avail;
> + }
> +
> env->nr_cpus_avail = (int)nr_cpus_avail;
[Severity: High]
Does clamping this value introduce a regression for header parsing on
machines with high core counts?
When process_cpu_topology() runs later, it uses env->nr_cpus_avail to
validate the number of sibling cores read from the file. If the file is
from a machine with 8192 cores, won't nr be 8192 while nr_cpus_avail was
clamped to MAX_NR_CPUS (e.g. 4096)?
This would cause the validation to fail and abort the entire session. Could
the clamp be applied dynamically during event delivery instead of modifying
the environment's true core count used for header validation?
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 7e25f75de37ab..bf14fa8c52f65 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -2076,14 +2076,89 @@ static int perf_session__deliver_event(struct perf_session *session,
[ ... ]
> + /*
> + * For perf.data files the MAX_NR_CPUS fallback in
> + * perf_session__read_header() guarantees this is set.
> + * For pipe mode, HEADER_NRCPUS may arrive late or not
> + * at all (pre-2017 perf, third-party tools). Fall
> + * back to MAX_NR_CPUS so the bounds check still works
> + * against fixed-size downstream arrays.
> + */
> + if (nr_cpus_avail <= 0) {
> + nr_cpus_avail = MAX_NR_CPUS;
> + perf_session__env(session)->nr_cpus_avail = nr_cpus_avail;
> + pr_warning_once("WARNING: HEADER_NRCPUS not set, using MAX_NR_CPUS (%d) as CPU bound\n",
> + MAX_NR_CPUS);
> + }
> + if (sample.cpu >= (u32)nr_cpus_avail &&
> + sample.cpu != (u32)-1) {
[Severity: High]
This is a pre-existing issue, but does skipping the bounds check for
(u32)-1 leave downstream tools vulnerable to out-of-bounds reads?
The code explicitly avoids clamping when sample.cpu == (u32)-1 to preserve
it as a sentinel. However, downstream tools like perf report and perf sched
often call test_bit(sample->cpu, rep->cpu_bitmap).
Since test_bit() does not verify if the index is a sentinel, won't it
zero-extend the (u32)-1 sentinel to a massive index and perform an
out-of-bounds read on the fixed-size cpu_bitmap[] array?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260521011027.622268-1-acme@kernel.org?part=25
next prev parent reply other threads:[~2026-05-21 2:43 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 1:09 [PATCHES 00/27] perf.data validation and hardening Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 01/27] perf session: Add minimum event size and alignment validation Arnaldo Carvalho de Melo
2026-05-21 1:59 ` sashiko-bot
2026-05-21 13:01 ` Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 02/27] perf tools: Fix event_contains() macro to verify full field extent Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 03/27] perf zstd: Fix compression error path in zstd_compress_stream_to_records() Arnaldo Carvalho de Melo
2026-05-21 1:49 ` sashiko-bot
2026-05-21 1:09 ` [PATCH 04/27] perf zstd: Fix multi-iteration decompression and error handling Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 05/27] perf session: Fix PERF_RECORD_READ swap and dump for variable-length events Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 06/27] perf session: Fix swap_sample_id_all() crash on crafted events Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 07/27] perf session: Add validated swap infrastructure with null-termination checks Arnaldo Carvalho de Melo
2026-05-21 1:52 ` sashiko-bot
2026-05-21 1:09 ` [PATCH 08/27] perf session: Use bounded copy for PERF_RECORD_TIME_CONV Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 09/27] perf session: Validate HEADER_ATTR attr.size before swapping Arnaldo Carvalho de Melo
2026-05-21 2:04 ` sashiko-bot
2026-05-21 1:09 ` [PATCH 10/27] perf session: Validate nr fields against event size on both swap and common paths Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 11/27] perf header: Byte-swap build ID event pid and bounds check section entries Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 12/27] perf cpumap: Reject RANGE_CPUS with start_cpu > end_cpu Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 13/27] perf auxtrace: Harden auxtrace_error event handling Arnaldo Carvalho de Melo
2026-05-21 1:09 ` [PATCH 14/27] perf session: Add byte-swap and bounds check for PERF_RECORD_BPF_METADATA events Arnaldo Carvalho de Melo
2026-05-21 2:23 ` sashiko-bot
2026-05-21 1:10 ` [PATCH 15/27] perf header: Validate null-termination in PERF_RECORD_EVENT_UPDATE string fields Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 16/27] perf tools: Bounds check perf_event_attr fields against attr.size before printing Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 17/27] perf header: Propagate feature section processing errors Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 18/27] perf header: Validate f_attr.ids section before use in perf_session__read_header() Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 19/27] perf header: Validate feature section size and add read path bounds checking Arnaldo Carvalho de Melo
2026-05-21 2:34 ` sashiko-bot
2026-05-21 1:10 ` [PATCH 20/27] perf header: Sanity check HEADER_EVENT_DESC attr.size before swap Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 21/27] perf header: Validate bitmap size before allocating in do_read_bitmap() Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 22/27] perf session: Add byte-swap for PERF_RECORD_COMPRESSED2 events Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 23/27] perf tools: Harden compressed event processing Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 24/27] perf session: Check for decompression buffer size overflow Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 25/27] perf session: Bound nr_cpus_avail and validate sample CPU Arnaldo Carvalho de Melo
2026-05-21 2:43 ` sashiko-bot [this message]
2026-05-21 1:10 ` [PATCH 26/27] perf kwork: Bounds check work->cpu before indexing cpus_runtime[] Arnaldo Carvalho de Melo
2026-05-21 1:10 ` [PATCH 27/27] perf test: Add truncated perf.data robustness test Arnaldo Carvalho de Melo
2026-05-21 2:07 ` sashiko-bot
2026-05-21 12:57 ` Arnaldo Carvalho de Melo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260521024338.346AE1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=acme@kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox