On Mon, Dec 4, 2023 at 3:40 PM Andrii Nakryiko <andrii@xxxxxxxxxx> wrote: > > Use the fact that we are passing subprog index around and have > a corresponding struct bpf_subprog_info in bpf_verifier_env for each > subprogram. We don't need to separately pass around a flag whether > subprog is exception callback or not, each relevant verifier function > can determine this using provided subprog index if we maintain > bpf_subprog_info properly. > > Also move out exception callback-specific logic from > btf_prepare_func_args(), keeping it generic. We can enforce all these > restriction right before exception callback verification pass. We add > out parameter, arg_cnt, for now, but this will be unnecessary with > subsequent refactoring and will be removed. > > Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx> > --- > include/linux/bpf.h | 2 +- > kernel/bpf/btf.c | 11 ++-------- > kernel/bpf/verifier.c | 51 ++++++++++++++++++++++++++++++++----------- > 3 files changed, 41 insertions(+), 23 deletions(-) > [...] > -static int do_check_common(struct bpf_verifier_env *env, int subprog, bool is_ex_cb) > +static int do_check_common(struct bpf_verifier_env *env, int subprog) > { > bool pop_log = !(env->log.level & BPF_LOG_LEVEL2); > struct bpf_verifier_state *state; > @@ -19842,9 +19860,22 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog, bool is_ex > > regs = state->frame[state->curframe]->regs; > if (subprog || env->prog->type == BPF_PROG_TYPE_EXT) { > - ret = btf_prepare_func_args(env, subprog, regs, is_ex_cb); > + u32 nargs; > + > + ret = btf_prepare_func_args(env, subprog, regs, &nargs); > if (ret) > goto out; > + if (subprog_is_exc_cb(env, subprog)) { > + state->frame[0]->in_exception_callback_fn = true; > + /* We have already ensured that the callback returns an integer, just > + * like all global subprogs. We need to determine it only has a single > + * scalar argument. > + */ > + if (nargs != 1 || regs[BPF_REG_1].type != SCALAR_VALUE) { > + verbose(env, "exception cb only supports single integer argument\n"); > + return -EINVAL; this should set ret and do goto out, fixed locally > + } > + } > for (i = BPF_REG_1; i <= BPF_REG_5; i++) { > if (regs[i].type == PTR_TO_CTX) > mark_reg_known_zero(env, regs, i); [...]