On Wed, Dec 15, 2021 at 7:21 PM Matteo Croce <mcroce@xxxxxxxxxxxxxxxxxxx> wrote: > > On Wed, Dec 15, 2021 at 6:29 PM Alexei Starovoitov > <alexei.starovoitov@xxxxxxxxx> wrote: > > > > On Wed, Dec 15, 2021 at 6:54 AM Matteo Croce <mcroce@xxxxxxxxxxxxxxxxxxx> wrote: > > > > > > > > Maybe do a level check here? > > > > Since calling it and immediately returning doesn't conserve > > > > the stack. > > > > If it gets called it can finish fine, but > > > > calling it again would be too much. > > > > In other words checking the level here gives us > > > > room for one more frame. > > > > > > > > > > I thought that the compiler was smart enough to return before > > > allocating most of the frame. > > > I tried and this is true only with gcc, not with clang. > > > > Interesting. That's a surprise. > > Could you share the asm that gcc generates? > > > > Sure, > > This is the gcc x86_64 asm on a stripped down > bpf_core_types_are_compat() with a 1k struct on the stack: > > bpf_core_types_are_compat: > test esi, esi > jle .L69 > push r15 > push r14 > push r13 > push r12 > push rbp > mov rbp, rdi > push rbx > mov ebx, esi > sub rsp, 9112 > [...] > .L69: > or eax, -1 > ret > > This latest clang: > > bpf_core_types_are_compat: # @bpf_core_types_are_compat > push rbp > push r15 > push r14 > push rbx > sub rsp, 1000 > mov r14d, -1 > test esi, esi > jle .LBB0_7 > [...] > .LBB0_7: > mov eax, r14d > add rsp, 1000 > pop rbx > pop r14 > pop r15 > pop rbp > ret > > > > > > + err = __bpf_core_types_are_compat(local_btf, local_id, > > > > > + targ_btf, targ_id, > > > > > + level - 1); > > > > > + if (err <= 0) > > > > > + return err; > > > > > + } > > > > > + > > > > > + /* tail recurse for return type check */ > > > > > + btf_type_skip_modifiers(local_btf, local_type->type, &local_id); > > > > > + btf_type_skip_modifiers(targ_btf, targ_type->type, &targ_id); > > > > > + goto recur; > > > > > + } > > > > > + default: > > > > > + pr_warn("unexpected kind %s relocated, local [%d], target [%d]\n", > > > > > + btf_type_str(local_type), local_id, targ_id); > > > > > > > > That should be bpf_log() instead. > > > > > > > > > > To do that I need a struct bpf_verifier_log, which is not present > > > there, neither in bpf_core_spec_match() or bpf_core_apply_relo_insn(). > > > > It is there. See: > > err = bpf_core_apply_relo_insn((void *)ctx->log, insn, ... > > > > > Should we drop the message at all? > > > > Passing it into bpf_core_spec_match() and further into > > bpf_core_types_are_compat() is probably unnecessary. > > All callers have an error check with a log right after. > > So I think we won't lose anything if we drop this log. > > > > Nice. > > > > > > > > > + return 0; > > > > > + } > > > > > +} > > > > > > > > Please add tests that exercise this logic by enabling > > > > additional lskels and a new test that hits the recursion limit. > > > > I suspect we don't have such case in selftests. > > > > > > > > Thanks! > > > > > > Will do! > > > > Thanks! > Hi, I'm writing a test which exercise that function. I can succesfully trigger a call to __bpf_core_types_are_compat() with these calls: bpf_core_type_id_kernel(struct sk_buff); bpf_core_type_exists(struct sk_buff); bpf_core_type_size(struct sk_buff); but the kind will obviously be BTF_KIND_STRUCT. I'm trying to do the same with kind BTF_KIND_FUNC_PROTO instead with: void func_proto(int, unsigned int); bpf_core_type_id_kernel(func_proto); but I get a clang crash[1], while just checking the existence with: typedef int (*func_proto_typedef)(struct sk_buff *); bpf_core_type_exists(func_proto_typedef); I don't reach even bpf_core_spec_match(). Which is a simple way to generate a BTF_KIND_FUNC_PROTO BTF field? [1] https://github.com/llvm/llvm-project/issues/52779 Regards, -- per aspera ad upstream