mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value()
@ 2026-11-13 22:34 Hungyu Lin
  2026-11-14  5:58 ` Alexei Starovoitov
  0 siblings, 1 reply; 2+ messages in thread
From: Hungyu Lin @ 2026-11-13 22:34 UTC (permalink / raw)
  To: andrii, bpf
  Cc: eddyz87, ihor.solodrai, ast, daniel, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, alan.maguire, linux-kernel,
	dennylin0707

btf_dump_get_enum_value() reads unaligned enum values through
btf_dump_get_bitfield_value() with a zero bit size. That path
zero-extends the value instead of using the signed loads that are used
for aligned data, so a negative value of a signed enum loses its
enumerator name when the data is unaligned.

Fix this by copying unaligned enum data into an aligned buffer, after
checking that the whole value is within the data, 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 | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index bbe86928b3ec..30fe3bb48df6 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -2329,16 +2329,13 @@ 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)) {
+		if (data + t->size > d->typed_dump->data_end)
+			return -E2BIG;
+		memcpy(buf, data, t->size);
+		data = buf;
 	}
 
 	switch (t->size) {

base-commit: 0021f17128de5dc0b19f1a523f448df2440d8088
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH bpf-next] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value()
  2026-11-13 22:34 [PATCH bpf-next] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
@ 2026-11-14  5:58 ` Alexei Starovoitov
  0 siblings, 0 replies; 2+ messages in thread
From: Alexei Starovoitov @ 2026-11-14  5:58 UTC (permalink / raw)
  To: Hungyu Lin, andrii, bpf
  Cc: eddyz87, ihor.solodrai, daniel, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, alan.maguire, linux-kernel

On Fri, Nov 13, 2026 at 02:34 PM 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 path
> zero-extends the value instead of using the signed loads that are used

Not quite. bit_sz == 0 makes right_shift_bits == 64 in
  *value = (num << left_shift_bits) >> right_shift_bits;
That's undefined behavior for __u64 on both endians.
Pls say it in the commit log.

> +	if (t->size <= sizeof(buf) && !ptr_is_aligned(d->btf, id, data)) {
> +		if (data + t->size > d->typed_dump->data_end)
> +			return -E2BIG;

This breaks the dump of struct fs_context when emit_zeroes is not set.
'phase' is an enum bitfield of 8 bits, 3 bytes before the end of the
struct. btf_dump_type_data_check_zero() ignores bit_sz of an enum:

  btf_dump_struct_data()
    btf_dump_dump_type_data(data = end - 3, bit_sz = 8)
      btf_dump_type_data_check_overflow()    1 byte, ok
      btf_dump_type_data_check_zero()
        btf_dump_get_enum_value()            t->size == 4, unaligned
          end - 3 + 4 > data_end             -E2BIG

Today it reads 1 byte past data_end and the dump succeeds.
The over-read is an old bug of enum bitfields. It needs its own fix.
The fs_context test in test_btf_dump_struct_data() sets emit_zeroes,
so it doesn't notice.

Drop the check. btf_dump_int_data() copies without it.
The check against data_end belongs in one place for all types.

The first case below fails on bpf-next today.
The second case fails with this patch.
I didn't build it and didn't run it:

diff --git a/tools/testing/selftests/bpf/prog_tests/btf_dump.c b/tools/testing/selftests/bpf/prog_tests/btf_dump.c
index b5c90f7..d6fd993 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,

pw-bot: cr

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-14  5:58 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 22:34 [PATCH bpf-next] libbpf: Fix sign extension of unaligned enums in btf_dump_get_enum_value() Hungyu Lin
2026-11-14  5:58 ` Alexei Starovoitov

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®