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