On Fri, Sep 29, 2023 at 02:06:10PM -0700, Alexei Starovoitov wrote: > On Wed, Sep 27, 2023 at 6:27 AM Matt Bobrowski <mattbobrowski@xxxxxxxxxx> wrote: > > static void testing(void) { > > bpf_printk("testing"); > > } > > > > struct iter_ctx { > > void (*f) (void); > > }; > > static u64 iter_callback(struct bpf_map *map, u32 *key, > > u64 *value, struct iter_ctx *ctx) { > > if (ctx->f) { > > ctx->f(); > > } > > return 0; > > } > > > > SEC("lsm.s/file_open") > > int BPF_PROG(file_open, struct file *file) > > { > > struct iter_ctx iter_ctx = { > > .f = testing, > > }; > > bpf_for_each_map_elem(&map, iter_callback, &iter_ctx, 0); > > return 0; > > } > > ``` > ... > > The fundamental difference between the two call instructions if I'm > > not mistaken is that one attempts to perform a call using an immediate > > value as its source operand, whereas the other attempts to perform a > > call using a source register as its source operand. AFAIU, the latter > > is not currently permitted by the BPF verifier. Is that right? > > Correct. Indirect calls via 'callx' instruction are not supported yet. > Please use bpf_tail_call() as a workaround for now. Noted. > Over the years the verifier became progressively smarter and maybe > now is a good time to support true indirect calls. This is something that I wouldn't mind exploring myself as a little research/contribution project. Would you object to me taking this on? I feel as though this would give me an opportunity to develop a better understanding when it comes to the internals of the BPF subsystem. > For certain cases like your example above it's relatively easy to > add such support, but before we do that please describe the full use > case that you wanted to implement with indirect calls. For the specific example I provided above, using indirect calls was an approach that I considered using within one of our BPF programs in order to work around this [0] specific BPF verifier shortcoming. For the workaround, I needed to implement 2 BPF programs that more or less done the same thing using the same set of routines, but differed ever so slightly for one particular routine. The way I envisioned controlling that one small difference between the 2 BPF programs is by supplying in different function pointers within the iteration context passed to bpf_for_each_map_elem(), but I quickly figured out that it wasn't possible and now I'm left with some highly undersirable code duplication across the 2 BPF programs. Understandably, this was an incredibly trivial and niche use case where using indirect calls would nicely solve this kind of problem, but I'm almost certain I could find other places where using indirect calls would be considered incredibly useful. [0] https://lore.kernel.org/bpf/CAADnVQLkB4dkdje5hq9ZLW0fgiDhEWU0DW67zRtJzLOKTRGhbQ@xxxxxxxxxxxxxx/ /M