[PATCH] perf record: reject CPU indices equal to the mask size

From: Paul

Date: Fri Oct 30 2026 - 02:49:11 EST


From: Paul Moses <p@xxxxxxx>

record__mmap_cpu_mask_init() rejects CPU indices greater than nbits but
accepts nbits itself. Valid indices end at nbits - 1. When nbits is a
multiple of BITS_PER_LONG, __set_bit() accesses the word immediately past
the bitmap allocation.

User specified recording thread masks reach this write before they are
intersected with the selected CPU mask. For example, an affinity mask
containing CPU 64 overruns a bitmap allocated for 64 possible CPUs.

==40343==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7bbab4000018 at pc 0x6195de57af45 bp 0x7ffe25545d20 sp 0x7ffe25545d18
READ of size 8 at 0x7bbab4000018 thread T0

Reject indices greater than or equal to nbits before setting a bit.

Fixes: cbd7bfc7fd99 ("tools/perf: Fix out of bound access to cpu mask array")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Paul Moses <p@xxxxxxx>
---
tools/perf/builtin-record.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d7c8f490cb62..80aaad7d51ec 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -3689,8 +3689,8 @@ static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cp
return 0;

perf_cpu_map__for_each_cpu_skip_any(cpu, idx, cpus) {
- /* Return ENODEV is input cpu is greater than max cpu */
- if ((unsigned long)cpu.cpu > mask->nbits)
+ /* Return ENODEV if the CPU index is outside the mask. */
+ if ((unsigned long)cpu.cpu >= mask->nbits)
return -ENODEV;
__set_bit(cpu.cpu, mask->bits);
}
--
2.56.GIT