bpf: set 'changed' status if propagate_precision() did any updates
Add an out parameter to `propagate_precision()` to record whether any new precision bits were set during its execution. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20250611200836.4135542-5-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>pull/1309/head
parent
9a2a0d7924
commit
23b37d6165
|
|
@ -4678,7 +4678,9 @@ static void mark_all_scalars_imprecise(struct bpf_verifier_env *env, struct bpf_
|
|||
* finalized states which help in short circuiting more future states.
|
||||
*/
|
||||
static int __mark_chain_precision(struct bpf_verifier_env *env,
|
||||
struct bpf_verifier_state *starting_state, int regno)
|
||||
struct bpf_verifier_state *starting_state,
|
||||
int regno,
|
||||
bool *changed)
|
||||
{
|
||||
struct bpf_verifier_state *st = starting_state;
|
||||
struct backtrack_state *bt = &env->bt;
|
||||
|
|
@ -4686,13 +4688,14 @@ static int __mark_chain_precision(struct bpf_verifier_env *env,
|
|||
int last_idx = starting_state->insn_idx;
|
||||
int subseq_idx = -1;
|
||||
struct bpf_func_state *func;
|
||||
bool tmp, skip_first = true;
|
||||
struct bpf_reg_state *reg;
|
||||
bool skip_first = true;
|
||||
int i, fr, err;
|
||||
|
||||
if (!env->bpf_capable)
|
||||
return 0;
|
||||
|
||||
changed = changed ?: &tmp;
|
||||
/* set frame number from which we are starting to backtrack */
|
||||
bt_init(bt, starting_state->curframe);
|
||||
|
||||
|
|
@ -4738,8 +4741,10 @@ static int __mark_chain_precision(struct bpf_verifier_env *env,
|
|||
for_each_set_bit(i, mask, 32) {
|
||||
reg = &st->frame[0]->regs[i];
|
||||
bt_clear_reg(bt, i);
|
||||
if (reg->type == SCALAR_VALUE)
|
||||
if (reg->type == SCALAR_VALUE) {
|
||||
reg->precise = true;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4798,10 +4803,12 @@ static int __mark_chain_precision(struct bpf_verifier_env *env,
|
|||
bt_clear_frame_reg(bt, fr, i);
|
||||
continue;
|
||||
}
|
||||
if (reg->precise)
|
||||
if (reg->precise) {
|
||||
bt_clear_frame_reg(bt, fr, i);
|
||||
else
|
||||
} else {
|
||||
reg->precise = true;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap_from_u64(mask, bt_frame_stack_mask(bt, fr));
|
||||
|
|
@ -4816,10 +4823,12 @@ static int __mark_chain_precision(struct bpf_verifier_env *env,
|
|||
continue;
|
||||
}
|
||||
reg = &func->stack[i].spilled_ptr;
|
||||
if (reg->precise)
|
||||
if (reg->precise) {
|
||||
bt_clear_frame_slot(bt, fr, i);
|
||||
else
|
||||
} else {
|
||||
reg->precise = true;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
if (env->log.level & BPF_LOG_LEVEL2) {
|
||||
fmt_reg_mask(env->tmp_str_buf, TMP_STR_BUF_LEN,
|
||||
|
|
@ -4855,7 +4864,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env,
|
|||
|
||||
int mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
||||
{
|
||||
return __mark_chain_precision(env, env->cur_state, regno);
|
||||
return __mark_chain_precision(env, env->cur_state, regno, NULL);
|
||||
}
|
||||
|
||||
/* mark_chain_precision_batch() assumes that env->bt is set in the caller to
|
||||
|
|
@ -4864,7 +4873,7 @@ int mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|||
static int mark_chain_precision_batch(struct bpf_verifier_env *env,
|
||||
struct bpf_verifier_state *starting_state)
|
||||
{
|
||||
return __mark_chain_precision(env, starting_state, -1);
|
||||
return __mark_chain_precision(env, starting_state, -1, NULL);
|
||||
}
|
||||
|
||||
static bool is_spillable_regtype(enum bpf_reg_type type)
|
||||
|
|
@ -18893,7 +18902,9 @@ static int propagate_liveness(struct bpf_verifier_env *env,
|
|||
* propagate them into the current state
|
||||
*/
|
||||
static int propagate_precision(struct bpf_verifier_env *env,
|
||||
const struct bpf_verifier_state *old)
|
||||
const struct bpf_verifier_state *old,
|
||||
struct bpf_verifier_state *cur,
|
||||
bool *changed)
|
||||
{
|
||||
struct bpf_reg_state *state_reg;
|
||||
struct bpf_func_state *state;
|
||||
|
|
@ -18941,7 +18952,7 @@ static int propagate_precision(struct bpf_verifier_env *env,
|
|||
verbose(env, "\n");
|
||||
}
|
||||
|
||||
err = mark_chain_precision_batch(env, env->cur_state);
|
||||
err = __mark_chain_precision(env, cur, -1, changed);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
@ -19264,7 +19275,7 @@ hit:
|
|||
*/
|
||||
if (is_jmp_point(env, env->insn_idx))
|
||||
err = err ? : push_jmp_history(env, cur, 0, 0);
|
||||
err = err ? : propagate_precision(env, &sl->state);
|
||||
err = err ? : propagate_precision(env, &sl->state, cur, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue