On Thu, Jun 26, 2025 at 8:58 PM 陈乐 <tom2cat@xxxxxxxxxxx> wrote: > > Hi BPF maintainers, > > I'm reporting a bug I encountered in the BPF subsystem on Linux kernel version <<5.19.5>>, <<6.15.0-rc2-00577-g8066e388be48-dirty>>, <<6.15.3>>. > > I wrote a BPF program that triggered a verifier rejection, but at the same time, the kernel emitted a BUG() warning at <<kernel/bpf/hashtab.c:222>>, suggesting a potential kernel-side issue rather than just verifier rejection. Later on, I discovered that constructing any ebpf Verifier rejection behavior within the specified code snippets would trigger this kernel bug. > > - Miniest poc code: > > #include "vmlinux.h" > #include <bpf/bpf_helpers.h> > > struct mac_table_entry > { > struct bpf_timer expiration_timer; > __u32 ifindex; > __u64 last_seen_timestamp_ns; > struct in_addr border_ip; > }; > > struct > { > __uint(type, BPF_MAP_TYPE_HASH); > __type(key, struct mac_address); > __type(value, struct mac_table_entry); > __uint(max_entries, 4 * 1024 * 1024); > __uint(pinning, LIBBPF_PIN_BY_NAME); > } mac_table SEC(".maps"); > > SEC("xdp.frags") > long mac_xdp_func(struct xdp_md *ctx) > { > // Constructing any code segment that does not meet the requirements of BPF Validator > // can trigger a kernel BUG: sleeping function called from invalid context at kernel/bpf/hashtab.c:222: > while(1){ > __u32 j; > } > return XDP_PASS; > } > > char LICENSE[] SEC("license") = "Dual BSD/GPL"; > > - Kernel version: <<6.15.3...>> > - Architecture: <<x86_64>> > - dmesg excerpt: <<BUG: sleeping function called from invalid context at kernel/bpf/hashtab.c:222>> > > Detailed info including reproducible BPF program and kernel logs have been filed on Bugzilla: > > https://bugzilla.kernel.org/show_bug.cgi?id=220278 Thanks for the report. The stack trace is the following: [ 280.376885] __might_resched+0x494/0x610 [ 280.376892] ? __pfx___might_resched+0x10/0x10 [ 280.376900] ? __lock_acquire+0xaab/0xd10 [ 280.376909] htab_map_free_timers_and_wq+0x413/0xaa0 [ 280.376917] ? __pfx_i_callback+0x10/0x10 [ 280.376922] ? rcu_core+0xc6b/0x1760 [ 280.376927] ? __pfx_htab_map_free_timers_and_wq+0x10/0x10 [ 280.376932] bpf_map_put_with_uref+0x9f/0xc0 [ 280.376939] bpf_free_inode+0x118/0x170 [ 280.376945] rcu_core+0xcdf/0x1760 Here is the issue that the last uref decrement happens in rcu callback which is not sleepable, but htab_map_free_timers_and_wq() has cond_resched(). The fix might be this: diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 5c2e96b19392..ed8bff8d4684 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -790,7 +790,7 @@ const struct super_operations bpf_super_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, .show_options = bpf_show_options, - .free_inode = bpf_free_inode, + .destroy_inode = bpf_free_inode, };