Commit 618945fb authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

bpf: remove unnecessary prune and jump points

Don't mark some instructions as jump points when there are actually no
jumps and instructions are just processed sequentially. Such case is
handled naturally by precision backtracking logic without the need to
update jump history. See get_prev_insn_idx(). It goes back linearly by
one instruction, unless current top of jmp_history is pointing to
current instruction. In such case we use `st->jmp_history[cnt - 1].prev_idx`
to find instruction from which we jumped to the current instruction
non-linearly.

Also remove both jump and prune point marking for instruction right
after unconditional jumps, as program flow can get to the instruction
right after unconditional jump instruction only if there is a jump to
that instruction from somewhere else in the program. In such case we'll
mark such instruction as prune/jump point because it's a destination of
a jump.

This change has no changes in terms of number of instructions or states
processes across Cilium and selftests programs.
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/r/20221206233345.438540-4-andrii@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent a095f421
...@@ -12233,13 +12233,12 @@ static int visit_func_call_insn(int t, int insn_cnt, ...@@ -12233,13 +12233,12 @@ static int visit_func_call_insn(int t, int insn_cnt,
if (ret) if (ret)
return ret; return ret;
if (t + 1 < insn_cnt) { mark_prune_point(env, t + 1);
mark_prune_point(env, t + 1); /* when we exit from subprog, we need to record non-linear history */
mark_jmp_point(env, t + 1); mark_jmp_point(env, t + 1);
}
if (visit_callee) { if (visit_callee) {
mark_prune_point(env, t); mark_prune_point(env, t);
mark_jmp_point(env, t);
ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env, ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env,
/* It's ok to allow recursion from CFG point of /* It's ok to allow recursion from CFG point of
* view. __check_func_call() will do the actual * view. __check_func_call() will do the actual
...@@ -12273,15 +12272,13 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env) ...@@ -12273,15 +12272,13 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env)
return DONE_EXPLORING; return DONE_EXPLORING;
case BPF_CALL: case BPF_CALL:
if (insns[t].imm == BPF_FUNC_timer_set_callback) { if (insns[t].imm == BPF_FUNC_timer_set_callback)
/* Mark this call insn to trigger is_state_visited() check /* Mark this call insn as a prune point to trigger
* before call itself is processed by __check_func_call(). * is_state_visited() check before call itself is
* Otherwise new async state will be pushed for further * processed by __check_func_call(). Otherwise new
* exploration. * async state will be pushed for further exploration.
*/ */
mark_prune_point(env, t); mark_prune_point(env, t);
mark_jmp_point(env, t);
}
return visit_func_call_insn(t, insn_cnt, insns, env, return visit_func_call_insn(t, insn_cnt, insns, env,
insns[t].src_reg == BPF_PSEUDO_CALL); insns[t].src_reg == BPF_PSEUDO_CALL);
...@@ -12295,26 +12292,15 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env) ...@@ -12295,26 +12292,15 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env)
if (ret) if (ret)
return ret; return ret;
/* unconditional jmp is not a good pruning point,
* but it's marked, since backtracking needs
* to record jmp history in is_state_visited().
*/
mark_prune_point(env, t + insns[t].off + 1); mark_prune_point(env, t + insns[t].off + 1);
mark_jmp_point(env, t + insns[t].off + 1); mark_jmp_point(env, t + insns[t].off + 1);
/* tell verifier to check for equivalent states
* after every call and jump
*/
if (t + 1 < insn_cnt) {
mark_prune_point(env, t + 1);
mark_jmp_point(env, t + 1);
}
return ret; return ret;
default: default:
/* conditional jump with two edges */ /* conditional jump with two edges */
mark_prune_point(env, t); mark_prune_point(env, t);
mark_jmp_point(env, t);
ret = push_insn(t, t + 1, FALLTHROUGH, env, true); ret = push_insn(t, t + 1, FALLTHROUGH, env, true);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment