On Sat, Mar 05, 2022 at 03:13:33AM IST, Martin KaFai Lau wrote: > On Sat, Mar 05, 2022 at 02:18:56AM +0530, Kumar Kartikeya Dwivedi wrote: > > On Sat, Mar 05, 2022 at 01:58:30AM IST, Martin KaFai Lau wrote: > > > > diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h > > > > index 38b24ee8d8c2..7a684050495a 100644 > > > > --- a/include/linux/bpf_verifier.h > > > > +++ b/include/linux/bpf_verifier.h > > > > @@ -523,7 +523,8 @@ int check_ptr_off_reg(struct bpf_verifier_env *env, > > > > const struct bpf_reg_state *reg, int regno); > > > > int check_func_arg_reg_off(struct bpf_verifier_env *env, > > > > const struct bpf_reg_state *reg, int regno, > > > > - enum bpf_arg_type arg_type); > > > > + enum bpf_arg_type arg_type, > > > > + bool is_release_function); > > > > int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, > > > > u32 regno); > > > > int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, > > > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > > > > index 7f6a0ae5028b..c9a1019dc60d 100644 > > > > --- a/kernel/bpf/btf.c > > > > +++ b/kernel/bpf/btf.c > > > > @@ -5753,6 +5753,9 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, > > > > return -EINVAL; > > > > } > > > > > > > > + if (is_kfunc) > > > > + rel = btf_kfunc_id_set_contains(btf, resolve_prog_type(env->prog), > > > > + BTF_KFUNC_TYPE_RELEASE, func_id); > > > > /* check that BTF function arguments match actual types that the > > > > * verifier sees. > > > > */ > > > > @@ -5777,7 +5780,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, > > > > ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id); > > > > ref_tname = btf_name_by_offset(btf, ref_t->name_off); > > > > > > > > - ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE); > > > > + ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE, rel); > > > > if (ret < 0) > > > > return ret; > > > > > > > > @@ -5809,7 +5812,11 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, > > > > if (reg->type == PTR_TO_BTF_ID) { > > > > reg_btf = reg->btf; > > > > reg_ref_id = reg->btf_id; > > > > - /* Ensure only one argument is referenced PTR_TO_BTF_ID */ > > > > + /* Ensure only one argument is referenced > > > > + * PTR_TO_BTF_ID, check_func_arg_reg_off relies > > > > + * on only one referenced register being allowed > > > > + * for kfuncs. > > > > + */ > > > > if (reg->ref_obj_id) { > > > > if (ref_obj_id) { > > > > bpf_log(log, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n", > > > > @@ -5892,8 +5899,6 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, > > > > /* Either both are set, or neither */ > > > > WARN_ON_ONCE((ref_obj_id && !ref_regno) || (!ref_obj_id && ref_regno)); > > > > if (is_kfunc) { > > > This test is no longer needed? > > > > > > > If you mean the rel && !ref_obj_id below (which is guarded by this check), I do > > think it is needed, why do you think so? Because of the check in > > check_func_arg_reg_off? That only checks reg->off when it sees that both > > release_func and ref_obj_id are true, but ref_obj_id may not be set for any > > argument(s) passed to a release function, so we need to reject when we don't get > > atleast one referenced register for release function. > > > > Or were you referring to the WARN_ON_ONCE above it? > I meant the "if (is_kfunc)" test. rel can only be true > anyway when it is_kfunc. > Ah, indeed. I will remove it, but add a comment as well. > > > > - rel = btf_kfunc_id_set_contains(btf, resolve_prog_type(env->prog), > > > > - BTF_KFUNC_TYPE_RELEASE, func_id); > > > > /* We already made sure ref_obj_id is set only for one argument */ > > > > if (rel && !ref_obj_id) { > > > > bpf_log(log, "release kernel function %s expects refcounted PTR_TO_BTF_ID\n", > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > index e55bfd23e81b..c31407d156e7 100644 > > > > --- a/kernel/bpf/verifier.c > > > > +++ b/kernel/bpf/verifier.c > > > > @@ -5367,11 +5367,28 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > > > > > > > int check_func_arg_reg_off(struct bpf_verifier_env *env, > > > > const struct bpf_reg_state *reg, int regno, > > > > - enum bpf_arg_type arg_type) > > > > + enum bpf_arg_type arg_type, > > > > + bool is_release_func) > > > > { > > > > enum bpf_reg_type type = reg->type; > > > > + bool fixed_off_ok = false; > > > > int err; > > > > > > > > + /* When referenced PTR_TO_BTF_ID is passed to release function, it's > > > > + * fixed offset must be 0. We rely on the property that only one > > > > + * referenced register can be passed to BPF helpers and kfuncs. > > > > + */ > > > > + if (type == PTR_TO_BTF_ID) { > > > > + bool release_reg = is_release_func && reg->ref_obj_id; > > > > + > > > > + if (release_reg && reg->off) { > > > iiuc, the reason for not going through __check_ptr_off_reg() is > > > because it prefers a different verifier log message for release_reg > > > case for fixed off. How about var_off? > > > > > > > If reg->off is zero, we still call __check_ptr_off_reg with fixed_off_ok = > > false, which should handle non-zero var_off. > Understood that __check_ptr_off_reg handles both fixed_off and var_off case. > > The question was why only single out reg->off case to have a special message > but not the var_off case. The var_off case does not need a special message? > So my reasoning was, var_off is already disallowed even for normal case (it is rejected in check_ptr_to_btf_access as well), so we don't need a special message for that, just the existing one is fine. But reg->off is allowed, except in this case, so we can return a helpful message on why verifier is returning an error. > > > > > > + verbose(env, "R%d must have zero offset when passed to release func\n", > > > > + regno); > > > > + return -EINVAL; > > > > + } > > > > + fixed_off_ok = release_reg ? false : true; > > > nit. > > > fixed_off_ok = !release_reg; > > > > > > but this is a bit moot here considering the reg->off > > > check has already been done for the release_reg case. > > > > > > > Yes, it would be a redundant check inside __check_ptr_off_reg, but we still need > > to call it for checking bad var_off. > Redundant check is fine. > > The intention and the net effect here is fixed_off is always > allowed for the remaining case, so may as well directly set > fixed_off_ok to true. "fixed_off_ok = !release_reg;" > made me go back to re-read what else has not been handled > for the release_reg case but it could be just me being > slow here. > Right, I can see why that may be confusing. I just set it to !release_reg to disable any other code that may be added using that bool later in the future. > It will be useful to at least leave a comment here > on the redundant check and the remaining cases for > PTR_TO_BTF_ID actually always allow fixed_off. > Yes, I will add a comment to make it clearer. Thank you for your review. > > > > > > + } > > > > + > > > > switch ((u32)type) { > > > > case SCALAR_VALUE: > > > > /* Pointer types where reg offset is explicitly allowed: */ > > > > @@ -5394,8 +5411,7 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env, > > > > /* All the rest must be rejected: */ > > > > default: > > > > force_off_check: > > > > - err = __check_ptr_off_reg(env, reg, regno, > > > > - type == PTR_TO_BTF_ID); > > > > + err = __check_ptr_off_reg(env, reg, regno, fixed_off_ok); > > > > if (err < 0) > > > > return err; > > > > break; > > > > @@ -5452,11 +5468,14 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, > > > > if (err) > > > > return err; > > > > > > > > - err = check_func_arg_reg_off(env, reg, regno, arg_type); > > > > + err = check_func_arg_reg_off(env, reg, regno, arg_type, is_release_function(meta->func_id)); > > > > if (err) > > > > return err; > > > > > > > > skip_type_check: > > > > + /* check_func_arg_reg_off relies on only one referenced register being > > > > + * allowed for BPF helpers. > > > > + */ > > > > if (reg->ref_obj_id) { > > > > if (meta->ref_obj_id) { > > > > verbose(env, "verifier internal error: more than one arg with ref_obj_id R%d %u %u\n", > > > > -- > > > > 2.35.1 > > > > > > > > -- > > Kartikeya -- Kartikeya