* [PATCH] libbpf: Limit bitfield dump reads to checked bytes
@ 2026-07-08 2:58 Guangshuo Li
2026-07-08 3:10 ` sashiko-bot
2026-07-08 3:49 ` bot+bpf-ci
0 siblings, 2 replies; 4+ messages in thread
From: Guangshuo Li @ 2026-07-08 2:58 UTC (permalink / raw)
To: Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Varun R Mallya, bpf, linux-kernel
Cc: Guangshuo Li
btf_dump_get_bitfield_value() bounds-checks the number of bytes covered
by the bitfield, but the value-building loops read the full backing type
size. For narrow bitfields this can read past the checked range.
Checking the full backing type size is too strict for packed bitfields.
For example, a packed structure can contain an 8-bit field backed by an
int type whose BTF size is 4, while the actual object bytes covering the
field are only 1 byte.
Keep the bounds check based on the bytes covered by the field, and make
the value-building loops consume the same checked byte range. Preserve
the full-size read for the non-bitfield path used by unaligned enum
values.
Fixes: 5714ca8cba5e ("libbpf: Fix OOB read in btf_dump_get_bitfield_value")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
tools/lib/bpf/btf_dump.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index cc1ba65bb6c5..5d185f7961ff 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -1766,17 +1766,21 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
__u64 num = 0;
int i;
- /* Calculate how many bytes cover the bitfield */
- start_bit = bits_offset % 8;
- nr_bytes = (start_bit + bit_sz + 7) / 8;
+ if (bit_sz) {
+ /* Calculate how many bytes cover the bitfield */
+ start_bit = bits_offset % 8;
+ nr_bytes = (start_bit + bit_sz + 7) / 8;
+ } else {
+ nr_bytes = t->size;
+ }
/* Bound check */
if (data + nr_bytes > d->typed_dump->data_end)
return -E2BIG;
/* Maximum supported bitfield size is 64 bits */
- if (t->size > 8) {
- pr_warn("unexpected bitfield size %d\n", t->size);
+ if (nr_bytes < 1 || nr_bytes > 8) {
+ pr_warn("unexpected bitfield size %d\n", nr_bytes);
return -EINVAL;
}
@@ -1784,13 +1788,13 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
* stored in num, then we left/right shift num to eliminate irrelevant bits.
*/
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- for (i = t->size - 1; i >= 0; i--)
+ for (i = nr_bytes - 1; i >= 0; i--)
num = num * 256 + bytes[i];
- nr_copy_bits = bit_sz + bits_offset;
+ nr_copy_bits = bit_sz ? bit_sz + bits_offset : nr_bytes * 8;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- for (i = 0; i < t->size; i++)
+ for (i = 0; i < nr_bytes; i++)
num = num * 256 + bytes[i];
- nr_copy_bits = t->size * 8 - bits_offset;
+ nr_copy_bits = nr_bytes * 8 - bits_offset;
#else
# error "Unrecognized __BYTE_ORDER__"
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] libbpf: Limit bitfield dump reads to checked bytes
2026-07-08 2:58 [PATCH] libbpf: Limit bitfield dump reads to checked bytes Guangshuo Li
@ 2026-07-08 3:10 ` sashiko-bot
2026-07-08 3:12 ` Guangshuo Li
2026-07-08 3:49 ` bot+bpf-ci
1 sibling, 1 reply; 4+ messages in thread
From: sashiko-bot @ 2026-07-08 3:10 UTC (permalink / raw)
To: Guangshuo Li; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The patch introduces data corruption and undefined behavior when reading unaligned enums on Little Endian architectures by shifting a 64-bit integer by 64 bits.
--
--- Patch [1]: [PATCH] libbpf: Limit bitfield dump reads to checked bytes ---
commit 128a41a5de9f0bf022f4b652bb58245609c3162a
Author: Guangshuo Li <lgs201920130244@gmail.com>
libbpf: Limit bitfield dump reads to checked bytes
This commit updates btf_dump_get_bitfield_value() to limit the bitfield
value-building loops to the same checked byte range instead of the full
backing type size. It aims to prevent reading past the checked range for
narrow bitfields.
> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
[ ... ]
> @@ -1784,13 +1788,13 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
> * stored in num, then we left/right shift num to eliminate irrelevant bits.
> */
> #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> - for (i = t->size - 1; i >= 0; i--)
> + for (i = nr_bytes - 1; i >= 0; i--)
> num = num * 256 + bytes[i];
> - nr_copy_bits = bit_sz + bits_offset;
> + nr_copy_bits = bit_sz ? bit_sz + bits_offset : nr_bytes * 8;
> #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> - for (i = 0; i < t->size; i++)
> + for (i = 0; i < nr_bytes; i++)
> num = num * 256 + bytes[i];
> - nr_copy_bits = t->size * 8 - bits_offset;
> + nr_copy_bits = nr_bytes * 8 - bits_offset;
> #else
> # error "Unrecognized __BYTE_ORDER__"
> #endif
[Severity: Medium]
Does this change introduce data corruption for unaligned enums on Little
Endian architectures?
When bit_sz is 0 (for unaligned enums), nr_copy_bits now becomes
nr_bytes * 8 (e.g., 32 for a 4-byte enum).
The code immediately following this block in btf_dump_get_bitfield_value()
calculates:
left_shift_bits = 64 - nr_copy_bits;
right_shift_bits = 64 - bit_sz;
This results in left_shift_bits = 32, and right_shift_bits = 64.
The final shift evaluates to:
*value = (num << 32) >> 64;
Shifting a 64-bit integer by 64 bits is undefined behavior. On architectures
like x86 and ARM64, the shift amount is masked (modulo 64), meaning >> 64
executes as >> 0.
This results in (num << 32) >> 0, returning a corrupted value instead
of the expected unaligned enum value.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260708025807.702010-1-lgs201920130244@gmail.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] libbpf: Limit bitfield dump reads to checked bytes
2026-07-08 3:10 ` sashiko-bot
@ 2026-07-08 3:12 ` Guangshuo Li
0 siblings, 0 replies; 4+ messages in thread
From: Guangshuo Li @ 2026-07-08 3:12 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
Hi all,
Sorry, this email was sent by mistake. Please ignore it.
On Wed, 8 Jul 2026 at 11:10, <sashiko-bot@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] The patch introduces data corruption and undefined behavior when reading unaligned enums on Little Endian architectures by shifting a 64-bit integer by 64 bits.
> --
>
> --- Patch [1]: [PATCH] libbpf: Limit bitfield dump reads to checked bytes ---
> commit 128a41a5de9f0bf022f4b652bb58245609c3162a
> Author: Guangshuo Li <lgs201920130244@gmail.com>
> libbpf: Limit bitfield dump reads to checked bytes
>
> This commit updates btf_dump_get_bitfield_value() to limit the bitfield
> value-building loops to the same checked byte range instead of the full
> backing type size. It aims to prevent reading past the checked range for
> narrow bitfields.
>
> > diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> > --- a/tools/lib/bpf/btf_dump.c
> > +++ b/tools/lib/bpf/btf_dump.c
>
> [ ... ]
>
> > @@ -1784,13 +1788,13 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
> > * stored in num, then we left/right shift num to eliminate irrelevant bits.
> > */
> > #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> > - for (i = t->size - 1; i >= 0; i--)
> > + for (i = nr_bytes - 1; i >= 0; i--)
> > num = num * 256 + bytes[i];
> > - nr_copy_bits = bit_sz + bits_offset;
> > + nr_copy_bits = bit_sz ? bit_sz + bits_offset : nr_bytes * 8;
> > #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> > - for (i = 0; i < t->size; i++)
> > + for (i = 0; i < nr_bytes; i++)
> > num = num * 256 + bytes[i];
> > - nr_copy_bits = t->size * 8 - bits_offset;
> > + nr_copy_bits = nr_bytes * 8 - bits_offset;
> > #else
> > # error "Unrecognized __BYTE_ORDER__"
> > #endif
>
> [Severity: Medium]
> Does this change introduce data corruption for unaligned enums on Little
> Endian architectures?
>
> When bit_sz is 0 (for unaligned enums), nr_copy_bits now becomes
> nr_bytes * 8 (e.g., 32 for a 4-byte enum).
>
> The code immediately following this block in btf_dump_get_bitfield_value()
> calculates:
>
> left_shift_bits = 64 - nr_copy_bits;
> right_shift_bits = 64 - bit_sz;
>
> This results in left_shift_bits = 32, and right_shift_bits = 64.
> The final shift evaluates to:
>
> *value = (num << 32) >> 64;
>
> Shifting a 64-bit integer by 64 bits is undefined behavior. On architectures
> like x86 and ARM64, the shift amount is masked (modulo 64), meaning >> 64
> executes as >> 0.
>
> This results in (num << 32) >> 0, returning a corrupted value instead
> of the expected unaligned enum value.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260708025807.702010-1-lgs201920130244@gmail.com?part=1
Best,
Guangshuo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] libbpf: Limit bitfield dump reads to checked bytes
2026-07-08 2:58 [PATCH] libbpf: Limit bitfield dump reads to checked bytes Guangshuo Li
2026-07-08 3:10 ` sashiko-bot
@ 2026-07-08 3:49 ` bot+bpf-ci
1 sibling, 0 replies; 4+ messages in thread
From: bot+bpf-ci @ 2026-07-08 3:49 UTC (permalink / raw)
To: lgs201920130244, andrii, eddyz87, ast, daniel, memxor, martin.lau,
song, yonghong.song, jolsa, emil, varunrmallya, bpf, linux-kernel
Cc: lgs201920130244, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1500 bytes --]
> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> index 53c6624161d7..d82e8e425203 100644
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
[ ... ]
> @@ -1784,13 +1788,13 @@ static int btf_dump_get_bitfield_value(struct btf_dump *d,
> * stored in num, then we left/right shift num to eliminate irrelevant bits.
> */
> #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> - for (i = t->size - 1; i >= 0; i--)
> + for (i = nr_bytes - 1; i >= 0; i--)
> num = num * 256 + bytes[i];
> - nr_copy_bits = bit_sz + bits_offset;
> + nr_copy_bits = bit_sz ? bit_sz + bits_offset : nr_bytes * 8;
> #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> - for (i = 0; i < t->size; i++)
> + for (i = 0; i < nr_bytes; i++)
> num = num * 256 + bytes[i];
> - nr_copy_bits = t->size * 8 - bits_offset;
> + nr_copy_bits = nr_bytes * 8 - bits_offset;
Varun R Mallya asked in v2 for examples that can break the older
implementation, preferably with an ASAN report to justify the change.
Could you provide a test case or ASAN report demonstrating the issue? Without
demonstrable evidence of the OOB read, it's hard to evaluate whether this
change is necessary.
The previous review is at:
https://lore.kernel.org/bpf/akugPNylTrOa_bNn@computer
---
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/28914496440
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-08 3:49 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 2:58 [PATCH] libbpf: Limit bitfield dump reads to checked bytes Guangshuo Li
2026-07-08 3:10 ` sashiko-bot
2026-07-08 3:12 ` Guangshuo Li
2026-07-08 3:49 ` bot+bpf-ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox