BPF List
 help / color / mirror / Atom feed
* [PATCH] libbpf: bounds-check float size in btf_dump_float_data()
@ 2026-06-23  7:54 Naveed Khan
  2026-06-23  8:03 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Naveed Khan @ 2026-06-23  7:54 UTC (permalink / raw)
  To: bpf

btf_dump_float_data() copies t->size bytes from the object being dumped
into a fixed-size 16-byte on-stack union float_data whenever the source
data is not naturally aligned:

	union float_data fl;
	int sz = t->size;
	...
	if (!ptr_is_aligned(d->btf, type_id, data)) {
		memcpy(&fl, data, sz);
		flp = &fl;
	}

sz comes straight from the BTF type and is never bounded. libbpf does not
validate the size of a BTF_KIND_FLOAT type while parsing BTF
(btf_validate_type() just breaks for it), and
btf_dump_type_data_check_overflow() accepts any size below INT_MAX. A BTF
blob describing a FLOAT larger than sizeof(union float_data) therefore
makes the memcpy() write past fl and smash the stack when such a value is
formatted via btf_dump__dump_type_data().

btf_dump_int_data() already rejects out-of-range sizes before its copy;
add the same check to the float path.

Signed-off-by: Naveed Khan <naveed@digiscrypt.com>
---
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index cc1ba65bb6..922c8ce32c 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -1983,6 +1983,11 @@ static int btf_dump_float_data(struct btf_dump *d,
 	union float_data fl;
 	int sz = t->size;
 
+	if (sz < 0 || sz > sizeof(fl)) {
+		pr_warn("unexpected size %d for id [%u]\n", sz, type_id);
+		return -EINVAL;
+	}
+
 	/* handle unaligned data; copy to local union */
 	if (!ptr_is_aligned(d->btf, type_id, data)) {
 		memcpy(&fl, data, sz);
-- 
2.52.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] libbpf: bounds-check float size in btf_dump_float_data()
  2026-06-23  7:54 [PATCH] libbpf: bounds-check float size in btf_dump_float_data() Naveed Khan
@ 2026-06-23  8:03 ` sashiko-bot
  2026-06-23  8:29 ` bot+bpf-ci
  2026-06-23 20:43 ` Andrii Nakryiko
  2 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-23  8:03 UTC (permalink / raw)
  To: Naveed Khan; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Architecture-dependent bounds check breaks dumping of 16-byte floats on 32-bit architectures
--

commit 31fd1a7664b926003f6e360a24ed9cc2bcd8b9c5
Author: Naveed Khan <naveed@digiscrypt.com>

libbpf: bounds-check float size in btf_dump_float_data()

This commit adds a bounds check to btf_dump_float_data() in libbpf to
prevent a stack buffer overflow. It ensures the size of the float type from
the BTF data doesn't exceed the size of the local union used for unaligned
copies.

> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> index cc1ba65bb6c5a..922c8ce32c2ff 100644
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
> @@ -1983,6 +1983,11 @@ static int btf_dump_float_data(struct btf_dump *d,
>  	union float_data fl;
>  	int sz = t->size;
>  
> +	if (sz < 0 || sz > sizeof(fl)) {
> +		pr_warn("unexpected size %d for id [%u]\n", sz, type_id);
> +		return -EINVAL;
> +	}
> +

[Severity: Medium]
Does this bounds check prevent dumping 16-byte floats when running on 32-bit
architectures?

On 32-bit architectures, sizeof(union float_data) may be 8 or 12 depending on
the size of long double. If we process a valid float type with sz = 16, this
check will evaluate to true and return -EINVAL.

Looking further down in btf_dump_float_data(), the function has a handler for
16-byte floats:

	switch (sz) {
	case 16:
		btf_dump_type_values(d, "%Lf", flp->ld);
		break;

Because sz == 16 is expected, this check makes the case 16: statement
unreachable on those platforms.

Should this code allocate a fixed 16-byte stack buffer to receive the
memcpy() instead of relying on the architecture-dependent size of
union float_data?

>  	/* handle unaligned data; copy to local union */
>  	if (!ptr_is_aligned(d->btf, type_id, data)) {
>  		memcpy(&fl, data, sz);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/178220124597.31744.3595561672327420327@digiscrypt.com?part=1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] libbpf: bounds-check float size in btf_dump_float_data()
  2026-06-23  7:54 [PATCH] libbpf: bounds-check float size in btf_dump_float_data() Naveed Khan
  2026-06-23  8:03 ` sashiko-bot
@ 2026-06-23  8:29 ` bot+bpf-ci
  2026-06-23 20:43 ` Andrii Nakryiko
  2 siblings, 0 replies; 6+ messages in thread
From: bot+bpf-ci @ 2026-06-23  8:29 UTC (permalink / raw)
  To: naveed, bpf
  Cc: ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
	ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]

> btf_dump_float_data() copies t->size bytes from the object being dumped
> into a fixed-size 16-byte on-stack union float_data whenever the source
> data is not naturally aligned:
>         union float_data fl;
>         int sz = t->size;
>         ...
>         if (!ptr_is_aligned(d->btf, type_id, data)) {
>                 memcpy(&fl, data, sz);
>                 flp = &fl;
>         }
> sz comes straight from the BTF type and is never bounded. libbpf does not
> validate the size of a BTF_KIND_FLOAT type while parsing BTF
> (btf_validate_type() just breaks for it), and
> btf_dump_type_data_check_overflow() accepts any size below INT_MAX. A BTF
> blob describing a FLOAT larger than sizeof(union float_data) therefore
> makes the memcpy() write past fl and smash the stack when such a value is
> formatted via btf_dump__dump_type_data().
> btf_dump_int_data() already rejects out-of-range sizes before its copy;
> add the same check to the float path.
> Signed-off-by: Naveed Khan <naveed@digiscrypt.com>

This looks like a fix for a stack buffer overflow that has been present
since the typed data dumper was added.  Should this carry a Fixes: tag?

  Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data")


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/28011525735

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] libbpf: bounds-check float size in btf_dump_float_data()
  2026-06-23  7:54 [PATCH] libbpf: bounds-check float size in btf_dump_float_data() Naveed Khan
  2026-06-23  8:03 ` sashiko-bot
  2026-06-23  8:29 ` bot+bpf-ci
@ 2026-06-23 20:43 ` Andrii Nakryiko
  2026-06-24 10:10   ` [PATCH v2] " Naveed Khan
  2 siblings, 1 reply; 6+ messages in thread
From: Andrii Nakryiko @ 2026-06-23 20:43 UTC (permalink / raw)
  To: Naveed Khan; +Cc: bpf

On Tue, Jun 23, 2026 at 12:56 AM Naveed Khan <naveed@digiscrypt.com> wrote:
>
> btf_dump_float_data() copies t->size bytes from the object being dumped
> into a fixed-size 16-byte on-stack union float_data whenever the source
> data is not naturally aligned:
>
>         union float_data fl;
>         int sz = t->size;
>         ...
>         if (!ptr_is_aligned(d->btf, type_id, data)) {
>                 memcpy(&fl, data, sz);
>                 flp = &fl;
>         }
>
> sz comes straight from the BTF type and is never bounded. libbpf does not
> validate the size of a BTF_KIND_FLOAT type while parsing BTF
> (btf_validate_type() just breaks for it), and
> btf_dump_type_data_check_overflow() accepts any size below INT_MAX. A BTF
> blob describing a FLOAT larger than sizeof(union float_data) therefore
> makes the memcpy() write past fl and smash the stack when such a value is
> formatted via btf_dump__dump_type_data().
>
> btf_dump_int_data() already rejects out-of-range sizes before its copy;
> add the same check to the float path.
>
> Signed-off-by: Naveed Khan <naveed@digiscrypt.com>
> ---
> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> index cc1ba65bb6..922c8ce32c 100644
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
> @@ -1983,6 +1983,11 @@ static int btf_dump_float_data(struct btf_dump *d,
>         union float_data fl;
>         int sz = t->size;
>
> +       if (sz < 0 || sz > sizeof(fl)) {
> +               pr_warn("unexpected size %d for id [%u]\n", sz, type_id);
> +               return -EINVAL;
> +       }
> +

earlier btf_dump_type_data_check_overflow() should prevent memcpy
below from reading below data boundaries, so there is no need to
protect from that. And then subsequent switch will validate one of
expected/supported float sizes. This logic seems to be fine as is.

pw-bot: cr


>         /* handle unaligned data; copy to local union */
>         if (!ptr_is_aligned(d->btf, type_id, data)) {
>                 memcpy(&fl, data, sz);
> --
> 2.52.0
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] libbpf: bounds-check float size in btf_dump_float_data()
  2026-06-23 20:43 ` Andrii Nakryiko
@ 2026-06-24 10:10   ` Naveed Khan
  2026-06-24 10:23     ` sashiko-bot
  0 siblings, 1 reply; 6+ messages in thread
From: Naveed Khan @ 2026-06-24 10:10 UTC (permalink / raw)
  To: bpf

libbpf: bounds-check float size in btf_dump_float_data()

btf_dump_float_data() copies t->size bytes from the object being dumped
into a fixed-size on-stack buffer whenever the source data is not
naturally aligned:

	union float_data fl;
	int sz = t->size;
	...
	if (!ptr_is_aligned(d->btf, type_id, data)) {
		memcpy(&fl, data, sz);
		flp = &fl;
	}

sz comes straight from the BTF type and is never bounded.
btf_validate_type() does not validate the size of a BTF_KIND_FLOAT type,
and btf_dump_type_data_check_overflow() only bounds the *source* read
against data_end, not the destination buffer. The switch on sz that
rejects unsupported sizes runs only *after* the memcpy, so a BTF blob
describing a FLOAT larger than the destination smashes the stack before
the size is ever validated.

Validate sz before the copy, mirroring btf_dump_int_data(). Use a fixed
16-byte aligned buffer as the destination rather than union float_data,
whose size is architecture-dependent (sizeof(long double) is 12 on some
32-bit ABIs), so that valid 16-byte long double floats are always
accepted.

Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data")
Signed-off-by: Naveed Khan <naveed@digiscrypt.com>
---
>From 27941d119a3e9815906e787728bac54de9737539 Mon Sep 17 00:00:00 2001
From: Naveed Khan <naveed@digiscrypt.com>
Date: Wed, 24 Jun 2026 15:23:56 +0530
Subject: [PATCH] libbpf: bounds-check float size in btf_dump_float_data()

btf_dump_float_data() copies t->size bytes from the object being dumped
into a fixed-size on-stack buffer whenever the source data is not
naturally aligned:

	union float_data fl;
	int sz = t->size;
	...
	if (!ptr_is_aligned(d->btf, type_id, data)) {
		memcpy(&fl, data, sz);
		flp = &fl;
	}

sz comes straight from the BTF type and is never bounded.
btf_validate_type() does not validate the size of a BTF_KIND_FLOAT type,
and btf_dump_type_data_check_overflow() only bounds the *source* read
against data_end, not the destination buffer. The switch on sz that
rejects unsupported sizes runs only *after* the memcpy, so a BTF blob
describing a FLOAT larger than the destination smashes the stack before
the size is ever validated.

Validate sz before the copy, mirroring btf_dump_int_data(). Use a fixed
16-byte aligned buffer as the destination rather than union float_data,
whose size is architecture-dependent (sizeof(long double) is 12 on some
32-bit ABIs), so that valid 16-byte long double floats are always
accepted.

Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data")
Signed-off-by: Naveed Khan <naveed@digiscrypt.com>
---
 tools/lib/bpf/btf_dump.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index cc1ba65bb6..dc26f3a160 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -1980,13 +1980,18 @@ static int btf_dump_float_data(struct btf_dump *d,
 			       const void *data)
 {
 	const union float_data *flp = data;
-	union float_data fl;
+	char buf[16] __attribute__((aligned(16)));
 	int sz = t->size;
 
-	/* handle unaligned data; copy to local union */
+	if (sz < 0 || sz > sizeof(buf)) {
+		pr_warn("unexpected size %d for id [%u]\n", sz, type_id);
+		return -EINVAL;
+	}
+
+	/* handle unaligned data; copy to local buffer */
 	if (!ptr_is_aligned(d->btf, type_id, data)) {
-		memcpy(&fl, data, sz);
-		flp = &fl;
+		memcpy(buf, data, sz);
+		flp = (void *)buf;
 	}
 
 	switch (sz) {
-- 
2.52.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] libbpf: bounds-check float size in btf_dump_float_data()
  2026-06-24 10:10   ` [PATCH v2] " Naveed Khan
@ 2026-06-24 10:23     ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-24 10:23 UTC (permalink / raw)
  To: Naveed Khan; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] A malicious BTF can bypass size checks by defining a FLOAT or PTR member with a bitfield size, leading to an out-of-bounds memory read.
- [High] A mismatch between the target BTF alignment and the host architecture alignment requirements can cause an unaligned memory access crash when reading floats.
--

commit 8b775a18b4de3665e91e05ddb075a75dc6ae1b43
Author: Naveed Khan <naveed@digiscrypt.com>
Subject: libbpf: bounds-check float size in btf_dump_float_data()

This commit fixes a stack buffer overflow in btf_dump_float_data() by
validating the float size before copying it into an on-stack buffer. It also
changes the buffer to be 16-byte aligned so that valid long double floats
are always accepted.

> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> index cc1ba65bb6c5a..dc26f3a160305 100644
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
> @@ -1980,13 +1980,18 @@ static int btf_dump_float_data(struct btf_dump *d,
[ ... ]
>  	/* handle unaligned data; copy to local buffer */
>  	if (!ptr_is_aligned(d->btf, type_id, data)) {
> -		memcpy(&fl, data, sz);
> -		flp = &fl;
> +		memcpy(buf, data, sz);

[Severity: High]
This isn't a bug introduced by this patch, but could a malicious BTF bypass
size checks here by defining a FLOAT or PTR member with a bitfield size?

Looking at btf_dump_type_data_check_overflow(), it short-circuits the full
size bounds check against data_end when bit_sz != 0, checking only the
bitfield size:

    if (bit_sz) {
        __u8 nr_bytes = (bits_offset + bit_sz + 7) / 8;
        return data + nr_bytes > d->typed_dump->data_end ? -E2BIG : nr_bytes;
    }

However, we unconditionally read t->size bytes from data via memcpy
above, which could lead to an out-of-bounds heap read if the actual
data buffer is smaller than t->size.

> +		flp = (void *)buf;
>  	}
>  
>  	switch (sz) {

[Severity: High]
This is a pre-existing issue, but could this cause an unaligned memory
access crash on certain architectures when reading 16-byte floats?

ptr_is_aligned() checks alignment against the BTF target requirements,
which caps at 8 bytes. If the host architecture requires 16-byte
alignment for a 16-byte long double, and the data pointer is only
8-byte aligned, ptr_is_aligned() returns true and bypasses the local
buffer copy.

Later in the switch statement:

    case 16:
        btf_dump_type_values(d, "%Lf", flp->ld);

Casting that 8-byte aligned data pointer to union float_data and accessing
flp->ld could cause an unaligned memory access trap.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/178229582410.80761.16669701451820050202@digiscrypt.com?part=1

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-24 10:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-23  7:54 [PATCH] libbpf: bounds-check float size in btf_dump_float_data() Naveed Khan
2026-06-23  8:03 ` sashiko-bot
2026-06-23  8:29 ` bot+bpf-ci
2026-06-23 20:43 ` Andrii Nakryiko
2026-06-24 10:10   ` [PATCH v2] " Naveed Khan
2026-06-24 10:23     ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox