All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Arnaldo Carvalho de Melo" <acme@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH 4/4] perf header: Validate bitmap size before allocating in do_read_bitmap()
Date: Tue, 14 Apr 2026 22:46:21 +0000	[thread overview]
Message-ID: <20260414224622.2AE69C19425@smtp.kernel.org> (raw)
In-Reply-To: <20260414204847.293557-5-acme@kernel.org>

Sashiko AI review found 2 potential issue(s):
- [Critical] Integer truncation in `bitmap_zalloc()` leads to a massive heap buffer overflow. While the added bounds check ensures `BITS_TO_U64(size)` elements fit in the declared section size, `bitmap_zalloc(int nbits)` explicitly takes a 32-bit signed integer. A crafted `size` (e.g., `0x100000040`) passes the 64-bit bounds check but truncates to 64 when passed to `bitmap_zalloc()`, allocating only 8 bytes. The un-truncated 64-bit size is then used as the upper bound for the read loop, causing `do_read_u64()` to write millions of elements sequentially past the 8-byte allocation until the physical end of the file is reached.
- [High] Architecture-dependent heap buffer overflow on 32-bit systems due to mismatched allocation and read sizes. On 32-bit architectures, `bitmap_zalloc(size)` allocates memory based on `sizeof(unsigned long)`, which is 4 bytes. However, `do_read_bitmap()` casts the allocated buffer to a `u64 *` and reads 8-byte chunks using `do_read_u64()`. For small bit counts like `size = 1`, `bitmap_zalloc()` allocates exactly 4 bytes, but the read loop executes once and writes 8 bytes, causing a 4-byte out-of-bounds heap write.
--

commit 6e9a72cba35d6256871d1af4ce151caaca2e76e2
Author: Arnaldo Carvalho de Melo <acme@redhat.com>

perf header: Validate bitmap size before allocating in do_read_bitmap()

This commit adds a bounds check in do_read_bitmap() to prevent large
allocations that exceed the remaining section size. It validates that
the requested bit count fits within the file data before calling
bitmap_zalloc().

> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -290,6 +290,9 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
>  	if (ret)
>  		return ret;
>  
> +	if (BITS_TO_U64(size) > (ff->size - ff->offset) / sizeof(u64))
> +		return -1;
> +
>  	set = bitmap_zalloc(size);

Does this code truncate the allocation size?

The size variable is a u64, but bitmap_zalloc() takes a 32-bit signed integer
for its nbits parameter. If a crafted file provides a large size value like
0x100000040, the 64-bit bounds check above would pass if the section is
large enough. 

However, the value would be truncated to 64 when passed to bitmap_zalloc(),
allocating only an 8 byte buffer.

[ ... ]

>  	p = (u64 *) set;
>  
>  	for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
>  		ret = do_read_u64(ff, p + i);

Could this loop write out of bounds on 32-bit architectures?

The bitmap_zalloc() function allocates memory based on sizeof(unsigned long),
which is 4 bytes on 32-bit architectures. For a small bit count like size = 1,
the allocation would be exactly 4 bytes.

Since the code casts the buffer to a u64 pointer and reads 8-byte chunks using
do_read_u64(), the first read would write 8 bytes, overflowing the 4-byte
allocation.

Could this loop also cause a heap buffer overflow due to the truncation
mentioned earlier?

If size is truncated by bitmap_zalloc() to a very small allocation, this
loop still uses the un-truncated 64-bit size as its upper bound. It would
sequentially write millions of elements past the small allocation until it
reaches the physical end of the file.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260414204847.293557-1-acme@kernel.org?part=4

  reply	other threads:[~2026-04-14 22:46 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-14 20:48 [PATCHES 0/4] More perf.data header validation Arnaldo Carvalho de Melo
2026-04-14 20:48 ` [PATCH 1/4] perf header: Add section bounds checking to the fd read path Arnaldo Carvalho de Melo
2026-04-14 21:24   ` sashiko-bot
2026-04-14 20:48 ` [PATCH 2/4] perf header: Validate string length before allocating in do_read_string() Arnaldo Carvalho de Melo
2026-04-14 21:51   ` sashiko-bot
2026-04-14 20:48 ` [PATCH 3/4] perf header: Sanity check HEADER_EVENT_DESC Arnaldo Carvalho de Melo
2026-04-14 22:20   ` sashiko-bot
2026-04-14 20:48 ` [PATCH 4/4] perf header: Validate bitmap size before allocating in do_read_bitmap() Arnaldo Carvalho de Melo
2026-04-14 22:46   ` sashiko-bot [this message]
2026-04-16  8:24 ` [PATCHES 0/4] More perf.data header validation James Clark

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=20260414224622.2AE69C19425@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=acme@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.