* [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.