Commit 6a42c494 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Greg Kroah-Hartman

bpf: move {prev_,}insn_idx into verifier env

commit c08435ec upstream.

Move prev_insn_idx and insn_idx from the do_check() function into
the verifier environment, so they can be read inside the various
helper functions for handling the instructions. It's easier to put
this into the environment rather than changing all call-sites only
to pass it along. insn_idx is useful in particular since this later
on allows to hold state in env->insn_aux_data[env->insn_idx].
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarVallish Vaidyeshwara <vallish@amazon.com>
[Backported to 4.14 by sblbir]
Signed-off-by: default avatarBalbir Singh <sblbir@amzn.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 85614894
...@@ -134,6 +134,8 @@ struct bpf_ext_analyzer_ops { ...@@ -134,6 +134,8 @@ struct bpf_ext_analyzer_ops {
* one verifier_env per bpf_check() call * one verifier_env per bpf_check() call
*/ */
struct bpf_verifier_env { struct bpf_verifier_env {
u32 insn_idx;
u32 prev_insn_idx;
struct bpf_prog *prog; /* eBPF program being verified */ struct bpf_prog *prog; /* eBPF program being verified */
struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
int stack_size; /* number of states to be processed */ int stack_size; /* number of states to be processed */
......
...@@ -3892,7 +3892,6 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3892,7 +3892,6 @@ static int do_check(struct bpf_verifier_env *env)
struct bpf_insn *insns = env->prog->insnsi; struct bpf_insn *insns = env->prog->insnsi;
struct bpf_reg_state *regs; struct bpf_reg_state *regs;
int insn_cnt = env->prog->len; int insn_cnt = env->prog->len;
int insn_idx, prev_insn_idx = 0;
int insn_processed = 0; int insn_processed = 0;
bool do_print_state = false; bool do_print_state = false;
...@@ -3902,19 +3901,18 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3902,19 +3901,18 @@ static int do_check(struct bpf_verifier_env *env)
env->cur_state = state; env->cur_state = state;
init_reg_state(state->regs); init_reg_state(state->regs);
state->parent = NULL; state->parent = NULL;
insn_idx = 0;
for (;;) { for (;;) {
struct bpf_insn *insn; struct bpf_insn *insn;
u8 class; u8 class;
int err; int err;
if (insn_idx >= insn_cnt) { if (env->insn_idx >= insn_cnt) {
verbose("invalid insn idx %d insn_cnt %d\n", verbose("invalid insn idx %d insn_cnt %d\n",
insn_idx, insn_cnt); env->insn_idx, insn_cnt);
return -EFAULT; return -EFAULT;
} }
insn = &insns[insn_idx]; insn = &insns[env->insn_idx];
class = BPF_CLASS(insn->code); class = BPF_CLASS(insn->code);
if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
...@@ -3923,7 +3921,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3923,7 +3921,7 @@ static int do_check(struct bpf_verifier_env *env)
return -E2BIG; return -E2BIG;
} }
err = is_state_visited(env, insn_idx); err = is_state_visited(env, env->insn_idx);
if (err < 0) if (err < 0)
return err; return err;
if (err == 1) { if (err == 1) {
...@@ -3931,9 +3929,9 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3931,9 +3929,9 @@ static int do_check(struct bpf_verifier_env *env)
if (log_level) { if (log_level) {
if (do_print_state) if (do_print_state)
verbose("\nfrom %d to %d: safe\n", verbose("\nfrom %d to %d: safe\n",
prev_insn_idx, insn_idx); env->prev_insn_idx, env->insn_idx);
else else
verbose("%d: safe\n", insn_idx); verbose("%d: safe\n", env->insn_idx);
} }
goto process_bpf_exit; goto process_bpf_exit;
} }
...@@ -3943,25 +3941,25 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3943,25 +3941,25 @@ static int do_check(struct bpf_verifier_env *env)
if (log_level > 1 || (log_level && do_print_state)) { if (log_level > 1 || (log_level && do_print_state)) {
if (log_level > 1) if (log_level > 1)
verbose("%d:", insn_idx); verbose("%d:", env->insn_idx);
else else
verbose("\nfrom %d to %d:", verbose("\nfrom %d to %d:",
prev_insn_idx, insn_idx); env->prev_insn_idx, env->insn_idx);
print_verifier_state(env->cur_state); print_verifier_state(env->cur_state);
do_print_state = false; do_print_state = false;
} }
if (log_level) { if (log_level) {
verbose("%d: ", insn_idx); verbose("%d: ", env->insn_idx);
print_bpf_insn(env, insn); print_bpf_insn(env, insn);
} }
err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx); err = ext_analyzer_insn_hook(env, env->insn_idx, env->prev_insn_idx);
if (err) if (err)
return err; return err;
regs = cur_regs(env); regs = cur_regs(env);
env->insn_aux_data[insn_idx].seen = true; env->insn_aux_data[env->insn_idx].seen = true;
if (class == BPF_ALU || class == BPF_ALU64) { if (class == BPF_ALU || class == BPF_ALU64) {
err = check_alu_op(env, insn); err = check_alu_op(env, insn);
if (err) if (err)
...@@ -3986,13 +3984,13 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -3986,13 +3984,13 @@ static int do_check(struct bpf_verifier_env *env)
/* check that memory (src_reg + off) is readable, /* check that memory (src_reg + off) is readable,
* the state of dst_reg will be updated by this func * the state of dst_reg will be updated by this func
*/ */
err = check_mem_access(env, insn_idx, insn->src_reg, insn->off, err = check_mem_access(env, env->insn_idx, insn->src_reg,
BPF_SIZE(insn->code), BPF_READ, insn->off, BPF_SIZE(insn->code),
insn->dst_reg, false); BPF_READ, insn->dst_reg, false);
if (err) if (err)
return err; return err;
prev_src_type = &env->insn_aux_data[insn_idx].ptr_type; prev_src_type = &env->insn_aux_data[env->insn_idx].ptr_type;
if (*prev_src_type == NOT_INIT) { if (*prev_src_type == NOT_INIT) {
/* saw a valid insn /* saw a valid insn
...@@ -4019,10 +4017,10 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4019,10 +4017,10 @@ static int do_check(struct bpf_verifier_env *env)
enum bpf_reg_type *prev_dst_type, dst_reg_type; enum bpf_reg_type *prev_dst_type, dst_reg_type;
if (BPF_MODE(insn->code) == BPF_XADD) { if (BPF_MODE(insn->code) == BPF_XADD) {
err = check_xadd(env, insn_idx, insn); err = check_xadd(env, env->insn_idx, insn);
if (err) if (err)
return err; return err;
insn_idx++; env->insn_idx++;
continue; continue;
} }
...@@ -4038,13 +4036,13 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4038,13 +4036,13 @@ static int do_check(struct bpf_verifier_env *env)
dst_reg_type = regs[insn->dst_reg].type; dst_reg_type = regs[insn->dst_reg].type;
/* check that memory (dst_reg + off) is writeable */ /* check that memory (dst_reg + off) is writeable */
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, err = check_mem_access(env, env->insn_idx, insn->dst_reg,
BPF_SIZE(insn->code), BPF_WRITE, insn->off, BPF_SIZE(insn->code),
insn->src_reg, false); BPF_WRITE, insn->src_reg, false);
if (err) if (err)
return err; return err;
prev_dst_type = &env->insn_aux_data[insn_idx].ptr_type; prev_dst_type = &env->insn_aux_data[env->insn_idx].ptr_type;
if (*prev_dst_type == NOT_INIT) { if (*prev_dst_type == NOT_INIT) {
*prev_dst_type = dst_reg_type; *prev_dst_type = dst_reg_type;
...@@ -4073,9 +4071,9 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4073,9 +4071,9 @@ static int do_check(struct bpf_verifier_env *env)
} }
/* check that memory (dst_reg + off) is writeable */ /* check that memory (dst_reg + off) is writeable */
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, err = check_mem_access(env, env->insn_idx, insn->dst_reg,
BPF_SIZE(insn->code), BPF_WRITE, insn->off, BPF_SIZE(insn->code),
-1, false); BPF_WRITE, -1, false);
if (err) if (err)
return err; return err;
...@@ -4091,7 +4089,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4091,7 +4089,7 @@ static int do_check(struct bpf_verifier_env *env)
return -EINVAL; return -EINVAL;
} }
err = check_call(env, insn->imm, insn_idx); err = check_call(env, insn->imm, env->insn_idx);
if (err) if (err)
return err; return err;
...@@ -4104,7 +4102,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4104,7 +4102,7 @@ static int do_check(struct bpf_verifier_env *env)
return -EINVAL; return -EINVAL;
} }
insn_idx += insn->off + 1; env->insn_idx += insn->off + 1;
continue; continue;
} else if (opcode == BPF_EXIT) { } else if (opcode == BPF_EXIT) {
...@@ -4132,7 +4130,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4132,7 +4130,7 @@ static int do_check(struct bpf_verifier_env *env)
} }
process_bpf_exit: process_bpf_exit:
err = pop_stack(env, &prev_insn_idx, &insn_idx); err = pop_stack(env, &env->prev_insn_idx, &env->insn_idx);
if (err < 0) { if (err < 0) {
if (err != -ENOENT) if (err != -ENOENT)
return err; return err;
...@@ -4142,7 +4140,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4142,7 +4140,7 @@ static int do_check(struct bpf_verifier_env *env)
continue; continue;
} }
} else { } else {
err = check_cond_jmp_op(env, insn, &insn_idx); err = check_cond_jmp_op(env, insn, &env->insn_idx);
if (err) if (err)
return err; return err;
} }
...@@ -4159,8 +4157,8 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4159,8 +4157,8 @@ static int do_check(struct bpf_verifier_env *env)
if (err) if (err)
return err; return err;
insn_idx++; env->insn_idx++;
env->insn_aux_data[insn_idx].seen = true; env->insn_aux_data[env->insn_idx].seen = true;
} else { } else {
verbose("invalid BPF_LD mode\n"); verbose("invalid BPF_LD mode\n");
return -EINVAL; return -EINVAL;
...@@ -4170,7 +4168,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -4170,7 +4168,7 @@ static int do_check(struct bpf_verifier_env *env)
return -EINVAL; return -EINVAL;
} }
insn_idx++; env->insn_idx++;
} }
verbose("processed %d insns, stack depth %d\n", verbose("processed %d insns, stack depth %d\n",
......
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