On Wed, Nov 29, 2023 at 04:03:59PM -0800, Andrii Nakryiko wrote: > Instead of relying on potentially imprecise tnum representation of > expected return value range for callbacks and subprogs, validate that > smin/smax range satisfy exact expected range of return values. > > E.g., if callback would need to return [0, 2] range, tnum can't > represent this precisely and instead will allow [0, 3] range. By > checking smin/smax range, we can make sure that subprog/callback indeed > returns only valid [0, 2] range. > > Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx> > Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx> Still recommend to inline retval_range_within(), using just tnum_range() , as per https://lore.kernel.org/bpf/ZWgcW2RCDW9hoOVI@u94a/ Otherwise LGTM Acked-by: Shung-Hsi Yu <shung-hsi.yu@xxxxxxxx> ... > +static struct tnum retval_range_as_tnum(struct bpf_retval_range range) > +{ > + if (range.minval == range.maxval) > + return tnum_const(range.minval); > + else > + return tnum_range(range.minval, range.maxval); > +} > + > static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) > { > struct bpf_verifier_state *state = env->cur_state, *prev_st; > @@ -9583,9 +9601,6 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) > > caller = state->frame[state->curframe - 1]; > if (callee->in_callback_fn) { > - /* enforce R0 return value range [0, 1]. */ > - struct tnum range = callee->callback_ret_range; > - > if (r0->type != SCALAR_VALUE) { > verbose(env, "R0 not a scalar value\n"); > return -EACCES; ...