* [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type
@ 2026-08-30 7:30 Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps Jiayuan Chen
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Jiayuan Chen @ 2026-08-30 7:30 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Mykyta Yatsenko,
Alan Maguire, linux-kernel, linux-kselftest
This series fixes two NULL-ptr-derefs in BTF handling.
Patch 1 handles the syzbot report. A key-less BTF (btf_key_type_id == 0) used
to be rejected for hash maps, until htab and rhtab gained a ->map_check_btf
(to register a dtor) that does not look at the key, so a key-less hash map is
now accepted. Dumping it through bpffs feeds the key type_id 0 into
btf_type_seq_show() and NULL-derefs in btf_type_show(). Reject it again.
Patch 2 fixes a related, pre-existing crash reachable via bpf_snprintf_btf().
A "const void" type_id (a modifier that resolves to void, present in the
vmlinux BTF) NULL-derefs in btf_modifier_show() - void has no ->show op.
void has no size and nothing to render, so route the show call sites through
a helper that falls back to btf_df_show() - the "<unsupported kind:N>"
placeholder already used for FWD/FUNC/FLOAT/DECL_TAG.
Patches 3 and 4 add selftests for the two cases. They are meant to reproduce
the crashes: each deliberately walks the faulting path, so on an unfixed
kernel it oopses the task (and panics it under panic_on_oops). That is
intentional - the tests verify the fix and reproduce the bug - so a static
review flagging them for crashing an unfixed kernel can be ignored.
v1 -> v2: AI reported a pre-exist issue. Let's fold it in this series.
v1: https://lore.kernel.org/bpf/20260828093142.179856-1-jiayuan.chen@linux.dev/
Jiayuan Chen (4):
bpf: Reject key-less BTF for hash maps
bpf: Fix NULL-ptr-deref when showing a void BTF type
selftests/bpf: Add test for key-less BTF hash map
selftests/bpf: Add test for showing a void BTF type
kernel/bpf/btf.c | 10 ++-
kernel/bpf/hashtab.c | 8 ++
.../bpf/prog_tests/btf_map_keyless.c | 83 +++++++++++++++++++
.../selftests/bpf/prog_tests/btf_show_void.c | 57 +++++++++++++
.../selftests/bpf/progs/btf_show_void.c | 22 +++++
5 files changed, 179 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_show_void.c
create mode 100644 tools/testing/selftests/bpf/progs/btf_show_void.c
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps
2026-08-30 7:30 [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type Jiayuan Chen
@ 2026-08-30 7:30 ` Jiayuan Chen
2026-08-30 8:35 ` bot+bpf-ci
2026-08-30 7:30 ` [PATCH bpf v2 2/4] bpf: Fix NULL-ptr-deref when showing a void BTF type Jiayuan Chen
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Jiayuan Chen @ 2026-08-30 7:30 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, syzbot+37b56485bbbf90ad8489, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai,
Shuah Khan, Mykyta Yatsenko, Alan Maguire, linux-kernel,
linux-kselftest
map_check_btf() allows a key-less BTF (btf_key_type_id == 0) only for
maps that have a ->map_check_btf callback, and leaves the actual
decision to that callback. Hash maps used to have no ->map_check_btf,
so a key-less BTF was rejected outright.
Since commit 1df97a7453ee ("bpf: Register dtor for freeing special
fields") htab and rhtab got a ->map_check_btf to register a dtor, but
it does not look at the key, so a key-less hash map now passes
map_check_btf() and gets created. Reading it back through bpffs then
feeds the key type_id 0 into btf_type_seq_show(); btf_type_by_id()
returns the void type, kind_ops[BTF_KIND_UNKN] is NULL, and
btf_type_show() dereferences it:
KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
RIP: 0010:btf_type_show (kernel/bpf/btf.c:8251)
Call Trace:
<TASK>
btf_type_seq_show_flags (kernel/bpf/btf.c:8269)
btf_type_seq_show (kernel/bpf/btf.c:8277)
htab_map_seq_show_elem (kernel/bpf/hashtab.c:1669)
map_seq_show (kernel/bpf/inode.c:293)
seq_read_iter (fs/seq_file.c:273)
seq_read (fs/seq_file.c:163)
vfs_read (fs/read_write.c:572)
ksys_read (fs/read_write.c:716)
__x64_sys_read (fs/read_write.c:725)
do_syscall_64 (arch/x86/entry/syscall_64.c:61)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
</TASK>
Reject a key-less BTF in htab_map_check_btf() and rhtab_map_check_btf(),
restoring the previous behavior.
Fixes: 1df97a7453ee ("bpf: Register dtor for freeing special fields")
Fixes: 6905f8601298 ("bpf: Allow special fields in resizable hashtab")
Reported-by: syzbot+37b56485bbbf90ad8489@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a8f4e88.27659fcc.2ceef7.0008.GAE@google.com/T/
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
kernel/bpf/hashtab.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index d40cb5dd446c..43123424183c 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -530,6 +530,10 @@ static int htab_map_check_btf(struct bpf_map *map, const struct btf *btf,
{
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ /* Hash maps have no use for a key-less BTF. */
+ if (btf_type_is_void(key_type))
+ return -EINVAL;
+
if (htab_is_prealloc(htab))
return 0;
/*
@@ -3110,6 +3114,10 @@ static int rhtab_map_check_btf(struct bpf_map *map, const struct btf *btf,
{
struct bpf_rhtab *rhtab = container_of(map, struct bpf_rhtab, map);
+ /* Hash maps have no use for a key-less BTF. */
+ if (btf_type_is_void(key_type))
+ return -EINVAL;
+
return bpf_ma_set_dtor(map, &rhtab->ma, rhtab_mem_dtor);
}
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf v2 2/4] bpf: Fix NULL-ptr-deref when showing a void BTF type
2026-08-30 7:30 [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps Jiayuan Chen
@ 2026-08-30 7:30 ` Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type Jiayuan Chen
3 siblings, 0 replies; 8+ messages in thread
From: Jiayuan Chen @ 2026-08-30 7:30 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Mykyta Yatsenko,
Alan Maguire, linux-kernel, linux-kselftest
btf_modifier_show() resolves the modifier and then calls
btf_type_ops(t)->show() unconditionally. For the void type (type_id 0,
BTF_KIND_UNKN) kind_ops[] has no entry, so ->show is NULL.
The map dump path cannot reach a void type (a map key/value must have a
size and void has none), but bpf_snprintf_btf() takes a type_id straight
from the BPF program, and a "const void" (a modifier that resolves to
void, present in the vmlinux BTF) NULL-derefs there:
KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
RIP: 0010:btf_modifier_show (kernel/bpf/btf.c:2914)
Call Trace:
<TASK>
btf_type_show (kernel/bpf/btf.c:8251)
btf_type_snprintf_show (kernel/bpf/btf.c:8321)
bpf_snprintf_btf (kernel/trace/bpf_trace.c:1047)
bpf_prog_test_run_raw_tp (net/bpf/test_run.c:829)
__sys_bpf (kernel/bpf/syscall.c:4804)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
</TASK>
void has no size, so there is nothing to render - not even a byte length
to fall back to dumping as raw hex. btf_df_show() is already the ->show
for the other kinds that carry no value to print - FWD, FUNC, FUNC_PROTO,
FLOAT and DECL_TAG - and emits an "<unsupported kind:N>" placeholder;
void belongs to the same group and only lacks a show op because it has
no kind_ops[] entry at all. Fall back to btf_df_show() in
btf_modifier_show() when the resolved type has no show op, so a void type
prints that placeholder instead of crashing; bpf_snprintf_btf() then
returns the length as usual.
Fixes: c4d0bfb45068 ("bpf: Add bpf_snprintf_btf helper")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
kernel/bpf/btf.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 91b8ce77f699..6e267c4c4e1f 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -2911,7 +2911,15 @@ static void btf_modifier_show(const struct btf *btf,
else
t = btf_type_skip_modifiers(btf, type_id, NULL);
- btf_type_ops(t)->show(btf, t, type_id, data, bits_offset, show);
+ /*
+ * A modifier can resolve to the void type (e.g. "const void"), which
+ * has no show op (kind_ops[BTF_KIND_UNKN] is NULL). Print a placeholder
+ * instead of dereferencing NULL.
+ */
+ if (!btf_type_ops(t))
+ btf_df_show(btf, t, type_id, data, bits_offset, show);
+ else
+ btf_type_ops(t)->show(btf, t, type_id, data, bits_offset, show);
}
static void btf_var_show(const struct btf *btf, const struct btf_type *t,
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map
2026-08-30 7:30 [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 2/4] bpf: Fix NULL-ptr-deref when showing a void BTF type Jiayuan Chen
@ 2026-08-30 7:30 ` Jiayuan Chen
2026-08-30 8:35 ` bot+bpf-ci
2026-08-30 7:30 ` [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type Jiayuan Chen
3 siblings, 1 reply; 8+ messages in thread
From: Jiayuan Chen @ 2026-08-30 7:30 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Mykyta Yatsenko,
Alan Maguire, linux-kernel, linux-kselftest
Create a hash and an rhash map with btf_key_type_id == 0 and expect
bpf_map_create() to fail with -EINVAL; a positive control with a real
key type confirms the rejection is about the key-less BTF. On an unfixed
kernel the map is created, and the test pins and reads it back to walk
the bpffs dump path, which reproduces the btf_type_show() NULL-deref - so
running it on an unfixed kernel oopses the reading task (and panics it
under panic_on_oops).
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
.../bpf/prog_tests/btf_map_keyless.c | 83 +++++++++++++++++++
1 file changed, 83 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c b/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
new file mode 100644
index 000000000000..43f0bb9bd578
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <test_progs.h>
+#include <bpf/btf.h>
+
+/*
+ * A hash map with a key-less BTF (btf_key_type_id == 0) used to NULL-deref in
+ * btf_type_show() when dumped via bpffs.
+ * A fixed kernel rejects such a map at creation; on an unfixed kernel the
+ * pin-and-read below deliberately walks that bpffs dump path, so it doubles
+ * as a reproducer: it oopses an unfixed kernel (and panics it under
+ * panic_on_oops).
+ */
+static void check_keyless(int map_type, __u32 map_flags, int btf_fd, int val_id)
+{
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+ const char *path = "/sys/fs/bpf/keyless_map";
+ __u32 key = 1, val = 0x41424344;
+ char buf[256];
+ int map_fd;
+ FILE *f;
+
+ opts.map_flags = map_flags;
+ opts.btf_fd = btf_fd;
+ opts.btf_value_type_id = val_id;
+
+ /*
+ * Positive control: the same map with a real key type must be accepted,
+ * so the -EINVAL below is about the key-less BTF and not some unrelated
+ * rejection (e.g. an unknown map type).
+ */
+ opts.btf_key_type_id = val_id;
+ map_fd = bpf_map_create(map_type, "keyed_map", 4, 4, 8, &opts);
+ if (!ASSERT_GE(map_fd, 0, "keyed create is accepted"))
+ return;
+ close(map_fd);
+
+ /* A key-less BTF must be rejected. */
+ opts.btf_key_type_id = 0;
+ map_fd = bpf_map_create(map_type, "keyless_map", 4, 4, 8, &opts);
+
+ if (map_fd >= 0) {
+ /* Unfixed kernel: reproduce the oops via the bpffs dump path. */
+ (void)bpf_map_update_elem(map_fd, &key, &val, 0);
+ if (bpf_obj_pin(map_fd, path) == 0) {
+ f = fopen(path, "r");
+ if (f) {
+ while (fgets(buf, sizeof(buf), f))
+ ;
+ fclose(f);
+ }
+ unlink(path);
+ }
+ close(map_fd);
+ }
+
+ ASSERT_EQ(map_fd, -EINVAL, "key-less create is rejected");
+}
+
+void test_btf_map_keyless(void)
+{
+ int btf_fd, val_id;
+ struct btf *btf;
+
+ btf = btf__new_empty();
+ if (!ASSERT_OK_PTR(btf, "btf__new_empty"))
+ return;
+
+ val_id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
+ if (!ASSERT_GT(val_id, 0, "btf__add_int"))
+ goto out;
+
+ if (!ASSERT_OK(btf__load_into_kernel(btf), "btf__load_into_kernel"))
+ goto out;
+ btf_fd = btf__fd(btf);
+
+ if (test__start_subtest("hash"))
+ check_keyless(BPF_MAP_TYPE_HASH, 0, btf_fd, val_id);
+ if (test__start_subtest("rhash"))
+ check_keyless(BPF_MAP_TYPE_RHASH, BPF_F_NO_PREALLOC, btf_fd, val_id);
+out:
+ btf__free(btf);
+}
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type
2026-08-30 7:30 [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type Jiayuan Chen
` (2 preceding siblings ...)
2026-08-30 7:30 ` [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map Jiayuan Chen
@ 2026-08-30 7:30 ` Jiayuan Chen
2026-08-30 8:35 ` bot+bpf-ci
3 siblings, 1 reply; 8+ messages in thread
From: Jiayuan Chen @ 2026-08-30 7:30 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Mykyta Yatsenko,
Alan Maguire, linux-kernel, linux-kselftest
Call bpf_snprintf_btf() with the type_id of a "const void" from the
vmlinux BTF and check the rendered output is the "<unsupported kind:0>"
placeholder. On an unfixed kernel this used to NULL-deref in
btf_modifier_show(), so the test doubles as a reproducer: it oopses the
task (and panics it under panic_on_oops).
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
.../selftests/bpf/prog_tests/btf_show_void.c | 57 +++++++++++++++++++
.../selftests/bpf/progs/btf_show_void.c | 22 +++++++
2 files changed, 79 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_show_void.c
create mode 100644 tools/testing/selftests/bpf/progs/btf_show_void.c
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_show_void.c b/tools/testing/selftests/bpf/prog_tests/btf_show_void.c
new file mode 100644
index 000000000000..546833199195
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/btf_show_void.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include <bpf/btf.h>
+#include "btf_show_void.skel.h"
+
+/*
+ * bpf_snprintf_btf() with the type_id of a "const void" (a modifier that
+ * resolves to void, present in the vmlinux BTF) used to NULL-deref in
+ * btf_modifier_show(). A fixed kernel prints the "<unsupported kind:0>"
+ * placeholder; on an unfixed kernel this oopses the task (and panics it under
+ * panic_on_oops), so it doubles as a reproducer.
+ */
+void test_btf_show_void(void)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ const struct btf_type *t;
+ struct btf_show_void *skel;
+ int i, n, cv = 0, err;
+ char ctx[16] = {};
+ struct btf *btf;
+
+ btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
+ if (!ASSERT_OK_PTR(btf, "btf__parse vmlinux"))
+ return;
+
+ n = btf__type_cnt(btf);
+ for (i = 1; i < n; i++) {
+ t = btf__type_by_id(btf, i);
+ if (btf_kind(t) == BTF_KIND_CONST && t->type == 0) {
+ cv = i;
+ break;
+ }
+ }
+ if (!ASSERT_GT(cv, 0, "find const void in vmlinux BTF"))
+ goto out_btf;
+
+ skel = btf_show_void__open();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ goto out_btf;
+ skel->rodata->const_void_id = cv;
+ if (!ASSERT_OK(btf_show_void__load(skel), "skel_load"))
+ goto out_skel;
+
+ topts.ctx_in = ctx;
+ topts.ctx_size_in = sizeof(ctx);
+ err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.dump_const_void),
+ &topts);
+ if (!ASSERT_OK(err, "test_run"))
+ goto out_skel;
+
+ ASSERT_EQ(skel->bss->ret, sizeof("<unsupported kind:0>") - 1, "ret");
+ ASSERT_STREQ(skel->bss->out, "<unsupported kind:0>", "placeholder");
+out_skel:
+ btf_show_void__destroy(skel);
+out_btf:
+ btf__free(btf);
+}
diff --git a/tools/testing/selftests/bpf/progs/btf_show_void.c b/tools/testing/selftests/bpf/progs/btf_show_void.c
new file mode 100644
index 000000000000..9fabd7372f89
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btf_show_void.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "btf_ptr.h"
+#include <bpf/bpf_helpers.h>
+
+const volatile __u32 const_void_id;
+char out[64];
+long ret;
+
+SEC("raw_tp/sys_enter")
+int dump_const_void(void *ctx)
+{
+ struct btf_ptr ptr = {
+ .ptr = ctx,
+ .type_id = const_void_id,
+ .flags = 0,
+ };
+
+ ret = bpf_snprintf_btf(out, sizeof(out), &ptr, sizeof(ptr), 0);
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps
2026-08-30 7:30 ` [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps Jiayuan Chen
@ 2026-08-30 8:35 ` bot+bpf-ci
0 siblings, 0 replies; 8+ messages in thread
From: bot+bpf-ci @ 2026-08-30 8:35 UTC (permalink / raw)
To: jiayuan.chen, bpf
Cc: jiayuan.chen, syzbot+37b56485bbbf90ad8489, ast, daniel, andrii,
eddyz87, memxor, martin.lau, song, yonghong.song, jolsa, emil,
ihor.solodrai, shuah, yatsenko, alan.maguire, linux-kernel,
linux-kselftest, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2906 bytes --]
> map_check_btf() allows a key-less BTF (btf_key_type_id == 0) only for
> maps that have a ->map_check_btf callback, and leaves the actual
> decision to that callback. Hash maps used to have no ->map_check_btf,
> so a key-less BTF was rejected outright.
>
> Since commit 1df97a7453ee ("bpf: Register dtor for freeing special
> fields") htab and rhtab got a ->map_check_btf to register a dtor, but
> it does not look at the key, so a key-less hash map now passes
> map_check_btf() and gets created.
Is this attribution accurate? Commit 1df97a7453ee did add
htab_map_check_btf() to the four htab ops structs (htab_map_ops,
htab_lru_map_ops, htab_percpu_map_ops, htab_lru_percpu_map_ops), but
BPF_MAP_TYPE_RHASH did not exist at that commit.
The rhtab regression was introduced three months later by the second
Fixes: commit 6905f8601298 ("bpf: Allow special fields in resizable
hashtab"), which added rhtab_map_check_btf() and rhtab_map_ops for the
first time.
Could the commit message distinguish which regression each Fixes: tag
addresses? As written, the sentence attributes both regressions to
1df97a7453ee.
> KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
> RIP: 0010:btf_type_show (kernel/bpf/btf.c:8251)
> Call Trace:
> <TASK>
> btf_type_seq_show_flags (kernel/bpf/btf.c:8269)
> btf_type_seq_show (kernel/bpf/btf.c:8277)
> htab_map_seq_show_elem (kernel/bpf/hashtab.c:1669)
> map_seq_show (kernel/bpf/inode.c:293)
> seq_read_iter (fs/seq_file.c:273)
> seq_read (fs/seq_file.c:163)
> vfs_read (fs/read_write.c:572)
> ksys_read (fs/read_write.c:716)
> __x64_sys_read (fs/read_write.c:725)
> do_syscall_64 (arch/x86/entry/syscall_64.c:61)
> entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> </TASK>
Does this match the syzbot report? Looking at the actual report at the
Closes: link, several details differ from what was quoted:
The syscall in the report was pread64:
ksys_pread64 [inline]
__x64_sys_pread64+0x1eb/0x250 fs/read_write.c:769
But the quoted trace shows read (ksys_read, __x64_sys_read).
The report shows traverse() frames that are missing here:
traverse.part.0 fs/seq_file.c:112
traverse fs/seq_file.c:99 [inline]
seq_read_iter+0x93f/0x1270 fs/seq_file.c:196
And seq_read_iter's line number is 196 in the report, not 273.
There is an extra btf_type_seq_show frame inserted here that is not in
the report.
The btf.c line numbers are shifted by +19: the report shows
btf_type_show at 8232, btf_type_seq_show_flags at 8250, and
btf_type_seq_show at 8258, but the quoted trace adds 19 to each.
Should the crash trace be quoted verbatim from the syzbot report rather
than edited?
---
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/33300136294
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map
2026-08-30 7:30 ` [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map Jiayuan Chen
@ 2026-08-30 8:35 ` bot+bpf-ci
0 siblings, 0 replies; 8+ messages in thread
From: bot+bpf-ci @ 2026-08-30 8:35 UTC (permalink / raw)
To: jiayuan.chen, bpf
Cc: jiayuan.chen, ast, daniel, andrii, eddyz87, memxor, martin.lau,
song, yonghong.song, jolsa, emil, ihor.solodrai, shuah, yatsenko,
alan.maguire, linux-kernel, linux-kselftest, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 913 bytes --]
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c b/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
> new file mode 100644
> index 0000000000000..43f0bb9bd5786
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_map_keyless.c
> @@ -0,0 +1,83 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#define _GNU_SOURCE
This isn't a bug, but is the #define _GNU_SOURCE needed here?
Everything the file uses looks like plain POSIX (fopen/fgets/fclose from
stdio.h, unlink/close from unistd.h, plus libbpf/BTF calls), and
lib.mk already passes -D_GNU_SOURCE= to selftest builds.
> +#include <test_progs.h>
> +#include <bpf/btf.h>
[ ... ]
---
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/33300136294
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type
2026-08-30 7:30 ` [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type Jiayuan Chen
@ 2026-08-30 8:35 ` bot+bpf-ci
0 siblings, 0 replies; 8+ messages in thread
From: bot+bpf-ci @ 2026-08-30 8:35 UTC (permalink / raw)
To: jiayuan.chen, bpf
Cc: jiayuan.chen, ast, daniel, andrii, eddyz87, memxor, martin.lau,
song, yonghong.song, jolsa, emil, ihor.solodrai, shuah, yatsenko,
alan.maguire, linux-kernel, linux-kselftest, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 5199 bytes --]
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_show_void.c b/tools/testing/selftests/bpf/prog_tests/btf_show_void.c
> new file mode 100644
> index 0000000000000..5468331991958
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_show_void.c
> @@ -0,0 +1,57 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <test_progs.h>
> +#include <bpf/btf.h>
> +#include "btf_show_void.skel.h"
> +
> +/*
> + * bpf_snprintf_btf() with the type_id of a "const void" (a modifier that
> + * resolves to void, present in the vmlinux BTF) used to NULL-deref in
> + * btf_modifier_show(). A fixed kernel prints the "<unsupported kind:0>"
> + * placeholder; on an unfixed kernel this oopses the task (and panics it under
> + * panic_on_oops), so it doubles as a reproducer.
> + */
> +void test_btf_show_void(void)
A subsystem pattern flags this as potentially concerning: this adds a
new standalone test file pair for one narrow case (a modifier resolving
to void in bpf_snprintf_btf(), exercising the btf_modifier_show() ->
btf_df_show() fallback). The directory already has
prog_tests/snprintf_btf.c (serial_test_snprintf_btf, driving
progs/netif_receive_skb.c which includes progs/btf_ptr.h) that exercises
bpf_snprintf_btf() output formatting for a range of types.
Would this case fit better as an additional case in that existing test
rather than as a new binary/skeleton pair?
The counter-argument: snprintf_btf.c is structured very differently - it
attaches a netif_receive_skb raw tracepoint and triggers it with
system("ping -c 1 127.0.0.1"), and still uses the deprecated CHECK()
macros. The new test instead needs a type_id discovered from the vmlinux
BTF at runtime injected through rodata, and drives the program with
bpf_prog_test_run_opts() rather than a real event. Folding it into the
existing test would mean adding a second program and a second run
mechanism to that file. That is a plausible engineering reason for a
separate file, and the new file is the more modern idiom.
> +{
> + LIBBPF_OPTS(bpf_test_run_opts, topts);
> + const struct btf_type *t;
> + struct btf_show_void *skel;
> + int i, n, cv = 0, err;
> + char ctx[16] = {};
> + struct btf *btf;
> +
> + btf = btf__parse("/sys/kernel/btf/vmlinux", NULL);
> + if (!ASSERT_OK_PTR(btf, "btf__parse vmlinux"))
> + return;
Both environment prerequisites of this test are reported as hard failures
rather than skips.
On a kernel built without CONFIG_DEBUG_INFO_BTF the /sys/kernel/btf/vmlinux
file does not exist, btf__parse() fails with ENOENT, and the test reports
a failure instead of a skip. The path is also hardcoded; btf__load_vmlinux_btf()
(used by 14 other prog_tests, e.g. fill_link_info.c, tracing_multi.c,
btf_module.c) additionally searches /boot/vmlinux-$(uname -r) and the
module build dirs.
> +
> + n = btf__type_cnt(btf);
> + for (i = 1; i < n; i++) {
> + t = btf__type_by_id(btf, i);
> + if (btf_kind(t) == BTF_KIND_CONST && t->type == 0) {
> + cv = i;
> + break;
> + }
> + }
> + if (!ASSERT_GT(cv, 0, "find const void in vmlinux BTF"))
> + goto out_btf;
The test scans the vmlinux BTF for the first BTF_KIND_CONST whose
->type == 0 and hard-fails via ASSERT_GT when none exists. Whether a
standalone const void node survives in a given kernel's BTF is a property
of that build (pahole version, dedup, whether anything in that kernel
actually uses const void *), not a property of the kernel logic under test.
If it is ever absent the test reports a kernel regression that is not
there, with no indication that the input the test needed simply was not
present.
Would a test__skip() with a reason string on both arms (the pattern used
in prog_tests/snprintf_btf.c) keep an environment difference from being
read as a failure?
Mitigating context: all BPF selftests already require CONFIG_DEBUG_INFO_BTF=y,
and the exact idiom btf__parse("/sys/kernel/btf/vmlinux", NULL) followed by
ASSERT_OK_PTR is used unchanged in prog_tests/libbpf_str.c (4 sites),
prog_tests/libbpf_probes.c (2 sites) and prog_tests/btf_sysfs.c, so the
first arm matches existing neighbours. const void is also very likely
present in any vmlinux BTF, since const void * appears in many exported
prototypes. The concern is robustness/diagnosability of the failure mode,
not a functional defect.
> +
> + skel = btf_show_void__open();
> + if (!ASSERT_OK_PTR(skel, "skel_open"))
> + goto out_btf;
> + skel->rodata->const_void_id = cv;
> + if (!ASSERT_OK(btf_show_void__load(skel), "skel_load"))
> + goto out_skel;
> +
> + topts.ctx_in = ctx;
> + topts.ctx_size_in = sizeof(ctx);
> + err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.dump_const_void),
> + &topts);
> + if (!ASSERT_OK(err, "test_run"))
> + goto out_skel;
> +
> + ASSERT_EQ(skel->bss->ret, sizeof("<unsupported kind:0>") - 1, "ret");
> + ASSERT_STREQ(skel->bss->out, "<unsupported kind:0>", "placeholder");
> +out_skel:
> + btf_show_void__destroy(skel);
> +out_btf:
> + btf__free(btf);
> +}
---
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/33300136294
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-08-30 8:35 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-30 7:30 [PATCH bpf v2 0/4] bpf: Fix NULL-ptr-derefs when showing a void BTF type Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 1/4] bpf: Reject key-less BTF for hash maps Jiayuan Chen
2026-08-30 8:35 ` bot+bpf-ci
2026-08-30 7:30 ` [PATCH bpf v2 2/4] bpf: Fix NULL-ptr-deref when showing a void BTF type Jiayuan Chen
2026-08-30 7:30 ` [PATCH bpf v2 3/4] selftests/bpf: Add test for key-less BTF hash map Jiayuan Chen
2026-08-30 8:35 ` bot+bpf-ci
2026-08-30 7:30 ` [PATCH bpf v2 4/4] selftests/bpf: Add test for showing a void BTF type Jiayuan Chen
2026-08-30 8:35 ` 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
all inboxes | Powered by JetHome®