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. Over the years the verifier became progressively smarter and maybe now is a good time to support true indirect calls. 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.