On Fri, Mar 19, 2021 at 12:32 PM Martin KaFai Lau <kafai@xxxxxx> wrote: > > On Thu, Mar 18, 2021 at 04:32:47PM -0700, Andrii Nakryiko wrote: > > On Tue, Mar 16, 2021 at 12:01 AM Martin KaFai Lau <kafai@xxxxxx> wrote: > > > > > > This patch refactors the core logic of "btf_check_func_arg_match()" > > > into a new function "do_btf_check_func_arg_match()". > > > "do_btf_check_func_arg_match()" will be reused later to check > > > the kernel function call. > > > > > > The "if (!btf_type_is_ptr(t))" is checked first to improve the indentation > > > which will be useful for a later patch. > > > > > > Some of the "btf_kind_str[]" usages is replaced with the shortcut > > > "btf_type_str(t)". > > > > > > Signed-off-by: Martin KaFai Lau <kafai@xxxxxx> > > > --- > > > include/linux/btf.h | 5 ++ > > > kernel/bpf/btf.c | 159 ++++++++++++++++++++++++-------------------- > > > 2 files changed, 91 insertions(+), 73 deletions(-) > > > [...] > > > + if (!btf_type_is_ptr(t)) { > > > + bpf_log(log, "Unrecognized arg#%d type %s\n", > > > + i, btf_type_str(t)); > > > + return -EINVAL; > > > + } > > > + > > > + ref_t = btf_type_skip_modifiers(btf, t->type, NULL); > > > + ref_tname = btf_name_by_offset(btf, ref_t->name_off); > > > > these two seem to be used only inside else `if (ptr_to_mem_ok)`, let's > > move the code and variables inside that branch? > It is kept here because the next patch uses it in > another case also. yeah, I saw that once I got to that patch, never mind > > > > > > + if (btf_get_prog_ctx_type(log, btf, t, env->prog->type, i)) { > > > /* If function expects ctx type in BTF check that caller > > > * is passing PTR_TO_CTX. > > > */ > > > - if (btf_get_prog_ctx_type(log, btf, t, prog->type, i)) { > > > - if (reg->type != PTR_TO_CTX) { > > > - bpf_log(log, > > > - "arg#%d expected pointer to ctx, but got %s\n", > > > - i, btf_kind_str[BTF_INFO_KIND(t->info)]); > > > - goto out; > > > - } > > > - if (check_ctx_reg(env, reg, i + 1)) > > > - goto out; > > > - continue; > > > + if (reg->type != PTR_TO_CTX) { > > > + bpf_log(log, > > > + "arg#%d expected pointer to ctx, but got %s\n", > > > + i, btf_type_str(t)); > > > + return -EINVAL; > > > } > > > + if (check_ctx_reg(env, reg, regno)) > > > + return -EINVAL; > > > > original code had `continue` here allowing to stop tracking if/else > > logic. Any specific reason you removed it? It keeps logic simpler to > > follow, imo. > There is no other case after this. > "continue" becomes redundant, so removed. well, there is the entire "else if (ptr_to_mem_ok)" which now you need to skip and go check if there is anything else that is supposed to happen after if. `continue;`, on the other hand, makes it very clear that nothing more is going to happen > > > > > > + } else if (ptr_to_mem_ok) { > > > > similarly to how you did reduction of nestedness with btf_type_is_ptr, I'd do > > > > if (!ptr_to_mem_ok) > > return -EINVAL; > > > > and let brain forget about another if/else branch tracking > I don't see a significant difference. Either way looks the same with > a few more test cases, IMO. > > I prefer to keep it like this since there is > another test case added in the next patch. > > There are usages with much longer if-else-if statement inside a > loop in the verifier also without explicit "continue" in the middle > or handle the last case differently and they are very readable. It's a matter of taste, I suppose. I'd probably disagree with you on the readability of those verifier parts ;) So it's up to you, of course, but for me this code pattern: for (...) { if (A) { handleA; } else if (B) { handleB; } else { return -EINVAL; } } is much harder to follow than more linear (imo) for (...) { if (A) { handleA; continue; } if (!B) return -EINVAL; handleB; } especially if handleA and handleB are quite long and complicated. Because I have to jump back and forth to validate that C is not allowed/handled later, and that there is no common subsequent logic for both A and B (or even C). In the latter code pattern there are clear "only A" and "only B" logic and it's quite obvious that no C is allowed/handled. > > > > > > + const struct btf_type *resolve_ret; > > > + u32 type_size; > > > > > > - if (!is_global) > > > - goto out; > > > - [...]