* [PATCH bpf-next v2 0/2] Fix unaligned enum values in btf_dump
@ 2026-11-15 8:49 Hungyu Lin
2026-11-15 8:49 ` [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
2026-11-15 8:49 ` [PATCH bpf-next v2 2/2] selftests/bpf: Dump unaligned enums and a zeroed fs_context Hungyu Lin
0 siblings, 2 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-15 8:49 UTC (permalink / raw)
To: andrii, bpf
Cc: ast, daniel, eddyz87, memxor, martin.lau, song, yonghong.song,
jolsa, emil, ihor.solodrai, alan.maguire, shuah, alexis.lothore,
luisflavieira, ameryhung, linux-kselftest, linux-kernel,
dennylin0707
btf_dump_get_enum_value() reads unaligned enum values through
btf_dump_get_bitfield_value() with a zero bit size, which shifts a
__u64 by 64. Patch 1 copies unaligned enum data into an aligned buffer
instead, as btf_dump_int_data() does. Patch 2 adds the tests Alexei
posted in the v1 review.
Changes in v2:
- Describe the undefined shift in the commit log.
- Drop the data_end check, which broke the dump of struct fs_context
without emit_zeroes.
- Add the selftests from the v1 review.
v1: https://lore.kernel.org/bpf/20261113223449.97604-1-dennylin0707@gmail.com/
Hungyu Lin (2):
libbpf: Fix sign extension of unaligned enums in
btf_dump_get_enum_value()
selftests/bpf: Dump unaligned enums and a zeroed fs_context
tools/lib/bpf/btf_dump.c | 13 ++++---------
tools/testing/selftests/bpf/prog_tests/btf_dump.c | 10 +++++++++-
2 files changed, 13 insertions(+), 10 deletions(-)
base-commit: 0021f17128de5dc0b19f1a523f448df2440d8088
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value()
2026-11-15 8:49 [PATCH bpf-next v2 0/2] Fix unaligned enum values in btf_dump Hungyu Lin
@ 2026-11-15 8:49 ` Hungyu Lin
2026-11-15 15:06 ` David Laight
2026-11-15 8:49 ` [PATCH bpf-next v2 2/2] selftests/bpf: Dump unaligned enums and a zeroed fs_context Hungyu Lin
1 sibling, 1 reply; 4+ messages in thread
From: Hungyu Lin @ 2026-11-15 8:49 UTC (permalink / raw)
To: andrii, bpf
Cc: ast, daniel, eddyz87, memxor, martin.lau, song, yonghong.song,
jolsa, emil, ihor.solodrai, alan.maguire, shuah, alexis.lothore,
luisflavieira, ameryhung, linux-kselftest, linux-kernel,
dennylin0707
btf_dump_get_enum_value() reads unaligned enum values through
btf_dump_get_bitfield_value() with a zero bit size. That makes
right_shift_bits 64 in
*value = (num << left_shift_bits) >> right_shift_bits;
which is undefined behavior for a __u64 on both endians. The path also
bypasses the signed loads used for aligned data, so a negative value of
a signed enum can lose its enumerator name when the data is unaligned.
Fix this by copying unaligned enum data into an aligned buffer, as
btf_dump_int_data() does, and reading it with the same loads as aligned
data.
Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data")
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
---
tools/lib/bpf/btf_dump.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index bbe86928b3ec..a80762a70cd0 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -2329,16 +2329,11 @@ static int btf_dump_get_enum_value(struct btf_dump *d,
__s64 *value)
{
bool is_signed = btf_kflag(t);
+ char buf[8] __attribute__((aligned(8)));
- if (!ptr_is_aligned(d->btf, id, data)) {
- __u64 val;
- int err;
-
- err = btf_dump_get_bitfield_value(d, t, data, 0, 0, &val);
- if (err)
- return err;
- *value = (__s64)val;
- return 0;
+ if (t->size <= sizeof(buf) && !ptr_is_aligned(d->btf, id, data)) {
+ memcpy(buf, data, t->size);
+ data = buf;
}
switch (t->size) {
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v2 2/2] selftests/bpf: Dump unaligned enums and a zeroed fs_context
2026-11-15 8:49 [PATCH bpf-next v2 0/2] Fix unaligned enum values in btf_dump Hungyu Lin
2026-11-15 8:49 ` [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
@ 2026-11-15 8:49 ` Hungyu Lin
1 sibling, 0 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-15 8:49 UTC (permalink / raw)
To: andrii, bpf
Cc: ast, daniel, eddyz87, memxor, martin.lau, song, yonghong.song,
jolsa, emil, ihor.solodrai, alan.maguire, shuah, alexis.lothore,
luisflavieira, ameryhung, linux-kselftest, linux-kernel,
dennylin0707
Dump the signed enum value from an unaligned address in the enum data
test. Also dump a zeroed struct fs_context without emit_zeroes in the
struct data test, which covers phase, an enum bitfield 3 bytes before
the end of the struct.
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
---
tools/testing/selftests/bpf/prog_tests/btf_dump.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_dump.c b/tools/testing/selftests/bpf/prog_tests/btf_dump.c
index b5c90f729339..d6fd9933ff25 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_dump.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_dump.c
@@ -945,7 +945,7 @@ static void test_btf_dump_enum_data(struct btf *btf, struct btf_dump *d,
char *str)
{
__u32 high = 0x80000000;
- __s32 neg = -1;
+ __s32 neg[2] = { -1, -1 };
/* enum where enum value does (and does not) exist */
TEST_BTF_DUMP_DATA_C(btf, d, "enum", str, enum bpf_cmd, BTF_F_COMPACT,
@@ -994,6 +994,8 @@ static void test_btf_dump_enum_data(struct btf *btf, struct btf_dump *d,
"(enum test_enum_u32)TEST_ENUM_HIGH"), "dump unsigned enum");
ASSERT_OK(btf_dump_data(btf, d, "test_enum_s32", NULL, 0, &neg, 4, str,
"(enum test_enum_s32)TEST_ENUM_NEG"), "dump signed enum");
+ ASSERT_OK(btf_dump_data(btf, d, "test_enum_s32", NULL, 0, (void *)neg + 1, 4, str,
+ "(enum test_enum_s32)TEST_ENUM_NEG"), "dump unaligned enum");
btf_dump__free(d);
}
@@ -1182,6 +1184,12 @@ static void test_btf_dump_struct_data(struct btf *btf, struct btf_dump *d,
type_sz = btf__resolve_size(btf, type_id);
str[0] = '\0';
+ /* 'phase' is an enum bitfield 3 bytes before the end */
+ ret = btf_dump__dump_type_data(d, type_id, zero_data, type_sz, &opts);
+ ASSERT_EQ(ret, type_sz,
+ "unexpected return value dumping zeroed fs_context");
+
+ str[0] = '\0';
opts.emit_zeroes = true;
ret = btf_dump__dump_type_data(d, type_id, zero_data, type_sz, &opts);
ASSERT_EQ(ret, type_sz,
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value()
2026-11-15 8:49 ` [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
@ 2026-11-15 15:06 ` David Laight
0 siblings, 0 replies; 4+ messages in thread
From: David Laight @ 2026-11-15 15:06 UTC (permalink / raw)
To: Hungyu Lin
Cc: andrii, bpf, ast, daniel, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, alan.maguire, shuah,
alexis.lothore, luisflavieira, ameryhung, linux-kselftest,
linux-kernel
On Sun, 15 Nov 2026 08:49:22 +0000
Hungyu Lin <dennylin0707@gmail.com> wrote:
> btf_dump_get_enum_value() reads unaligned enum values through
> btf_dump_get_bitfield_value() with a zero bit size. That makes
> right_shift_bits 64 in
>
> *value = (num << left_shift_bits) >> right_shift_bits;
>
> which is undefined behavior for a __u64 on both endians. The path also
> bypasses the signed loads used for aligned data, so a negative value of
> a signed enum can lose its enumerator name when the data is unaligned.
>
> Fix this by copying unaligned enum data into an aligned buffer, as
> btf_dump_int_data() does, and reading it with the same loads as aligned
> data.
>
> Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data")
> Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
> ---
> tools/lib/bpf/btf_dump.c | 13 ++++---------
> 1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
> index bbe86928b3ec..a80762a70cd0 100644
> --- a/tools/lib/bpf/btf_dump.c
> +++ b/tools/lib/bpf/btf_dump.c
> @@ -2329,16 +2329,11 @@ static int btf_dump_get_enum_value(struct btf_dump *d,
> __s64 *value)
> {
> bool is_signed = btf_kflag(t);
> + char buf[8] __attribute__((aligned(8)));
>
> - if (!ptr_is_aligned(d->btf, id, data)) {
> - __u64 val;
> - int err;
> -
> - err = btf_dump_get_bitfield_value(d, t, data, 0, 0, &val);
> - if (err)
> - return err;
> - *value = (__s64)val;
> - return 0;
> + if (t->size <= sizeof(buf) && !ptr_is_aligned(d->btf, id, data)) {
Do the alignment check first, you don't expect the size check to fail.
David
> + memcpy(buf, data, t->size);
> + data = buf;
> }
>
> switch (t->size) {
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-15 15:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-15 8:49 [PATCH bpf-next v2 0/2] Fix unaligned enum values in btf_dump Hungyu Lin
2026-11-15 8:49 ` [PATCH bpf-next v2 1/2] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
2026-11-15 15:06 ` David Laight
2026-11-15 8:49 ` [PATCH bpf-next v2 2/2] selftests/bpf: Dump unaligned enums and a zeroed fs_context Hungyu Lin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®