* [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; 7+ 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] 7+ 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; 7+ 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] 7+ 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; 7+ 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] 7+ 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; 7+ 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] 7+ 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
2026-06-24 16:49 ` Andrii Nakryiko
0 siblings, 2 replies; 7+ 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] 7+ 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
2026-06-24 16:49 ` Andrii Nakryiko
1 sibling, 0 replies; 7+ 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] 7+ 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
@ 2026-06-24 16:49 ` Andrii Nakryiko
1 sibling, 0 replies; 7+ messages in thread
From: Andrii Nakryiko @ 2026-06-24 16:49 UTC (permalink / raw)
To: Naveed Khan; +Cc: bpf
On Wed, Jun 24, 2026 at 3:10 AM Naveed Khan <naveed@digiscrypt.com> wrote:
>
> 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>
> ---
hm, did you see my previous reply? doesn't seem like your patch
addresses my concerns
> >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 [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-24 16:49 UTC | newest]
Thread overview: 7+ 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
2026-06-24 16:49 ` Andrii Nakryiko
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.