On Fri, Sep 5, 2025 at 1:42 AM Shung-Hsi Yu <shung-hsi.yu@xxxxxxxx> wrote: > > Adding some context that I think was miss per off-list discussion with > Hoyeon. > > On Fri, Sep 05, 2025 at 02:18:11PM +0900, Hoyeon Lee wrote: > > This RFC adds a compile-time check to bpf_tail_call_static() to warn > > when a constant slot(index) is >= map->max_entries. This uses a small > > BPF_MAP_ENTRIES() macro together with Clang's diagnose_if attribute. > > This is an attempt to see if it is possible to warn user of out-of-bound > tail calls, with the assumption being that with bpf_tail_call_static() > users would not be intentionally calling with an index that is superior > to the number of entries. > > However, there concerns with the current implementation, so this is > being sent as RFC to gather feedback, and to see if it can be better > done. Currently the concerns are: > - use macro to override bpf_tail_call_static() > - only works for Clang and not GCC > - uncertain whether this fit into libbpf conventions - map definition's max_entries can be set from user space at runtime making this check actively wrong This diagnose_if attribute seems very useful, but I'm not sure we should do this for anything map-related because statically provided map attributes are all overridable from user space when loading BPF object. > > > Clang front-end keeps the map type with a '(*max_entries)[N]' field, > > so the expression > > > > sizeof(*(m)->max_entries) / sizeof(**(m)->max_entries) > > > > is resolved to N entirely at compile time. This allows diagnose_if() > > to emit a warning when a constant slot index is out of range. > > > > Example: > > > > struct { /* BPF_MAP_TYPE_PROG_ARRAY = 3 */ > > __uint(type, 3); // int (*type)[3]; > > __uint(max_entries, 100); // int (*max_entries)[100]; > > __type(key, __u32); // typeof(__u32) *key; > > __type(value, __u32); // typeof(__u32) *value; > > } progs SEC(".maps"); > > > > bpf_tail_call_static(ctx, &progs, 111); > > > > produces: > > > > bound.bpf.c:26:9: warning: bpf_tail_call: slot >= max_entries [-Wuser-defined-warnings] > > 26 | bpf_tail_call_static(ctx, &progs, 111); > > | ^ > > /usr/local/include/bpf/bpf_helpers.h:190:54: note: expanded from macro 'bpf_tail_call_static' > > 190 | __bpf_tail_call_warn(__slot >= BPF_MAP_ENTRIES(map)); \ > > | ^ > > /usr/local/include/bpf/bpf_helpers.h:183:20: note: from 'diagnose_if' attribute on '__bpf_tail_call_warn': > > 183 | __attribute__((diagnose_if(oob, "bpf_tail_call: slot >= max_entries", "warning"))); > > | ^ ~~~ > > > > Out-of-bounds tail call checkup is no-ops at runtime. Emitting a > > compile-time warning can help developers detect mistakes earlier. The > > check is currently limited to Clang (due to diagnose_if) and constant > > indices, but should catch common errors. > ...