diff options
-rw-r--r-- | include/linux/bpf_verifier.h | 2 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 76 |
2 files changed, 40 insertions, 38 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index c233efc106c6..3f84f3e87704 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h | |||
@@ -212,6 +212,8 @@ struct bpf_subprog_info { | |||
212 | * one verifier_env per bpf_check() call | 212 | * one verifier_env per bpf_check() call |
213 | */ | 213 | */ |
214 | struct bpf_verifier_env { | 214 | struct bpf_verifier_env { |
215 | u32 insn_idx; | ||
216 | u32 prev_insn_idx; | ||
215 | struct bpf_prog *prog; /* eBPF program being verified */ | 217 | struct bpf_prog *prog; /* eBPF program being verified */ |
216 | const struct bpf_verifier_ops *ops; | 218 | const struct bpf_verifier_ops *ops; |
217 | struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ | 219 | struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 71d86e3024ae..afa8515bbb34 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -5650,7 +5650,6 @@ static int do_check(struct bpf_verifier_env *env) | |||
5650 | struct bpf_insn *insns = env->prog->insnsi; | 5650 | struct bpf_insn *insns = env->prog->insnsi; |
5651 | struct bpf_reg_state *regs; | 5651 | struct bpf_reg_state *regs; |
5652 | int insn_cnt = env->prog->len, i; | 5652 | int insn_cnt = env->prog->len, i; |
5653 | int insn_idx, prev_insn_idx = 0; | ||
5654 | int insn_processed = 0; | 5653 | int insn_processed = 0; |
5655 | bool do_print_state = false; | 5654 | bool do_print_state = false; |
5656 | 5655 | ||
@@ -5670,19 +5669,19 @@ static int do_check(struct bpf_verifier_env *env) | |||
5670 | BPF_MAIN_FUNC /* callsite */, | 5669 | BPF_MAIN_FUNC /* callsite */, |
5671 | 0 /* frameno */, | 5670 | 0 /* frameno */, |
5672 | 0 /* subprogno, zero == main subprog */); | 5671 | 0 /* subprogno, zero == main subprog */); |
5673 | insn_idx = 0; | 5672 | |
5674 | for (;;) { | 5673 | for (;;) { |
5675 | struct bpf_insn *insn; | 5674 | struct bpf_insn *insn; |
5676 | u8 class; | 5675 | u8 class; |
5677 | int err; | 5676 | int err; |
5678 | 5677 | ||
5679 | if (insn_idx >= insn_cnt) { | 5678 | if (env->insn_idx >= insn_cnt) { |
5680 | verbose(env, "invalid insn idx %d insn_cnt %d\n", | 5679 | verbose(env, "invalid insn idx %d insn_cnt %d\n", |
5681 | insn_idx, insn_cnt); | 5680 | env->insn_idx, insn_cnt); |
5682 | return -EFAULT; | 5681 | return -EFAULT; |
5683 | } | 5682 | } |
5684 | 5683 | ||
5685 | insn = &insns[insn_idx]; | 5684 | insn = &insns[env->insn_idx]; |
5686 | class = BPF_CLASS(insn->code); | 5685 | class = BPF_CLASS(insn->code); |
5687 | 5686 | ||
5688 | if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { | 5687 | if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) { |
@@ -5692,7 +5691,7 @@ static int do_check(struct bpf_verifier_env *env) | |||
5692 | return -E2BIG; | 5691 | return -E2BIG; |
5693 | } | 5692 | } |
5694 | 5693 | ||
5695 | err = is_state_visited(env, insn_idx); | 5694 | err = is_state_visited(env, env->insn_idx); |
5696 | if (err < 0) | 5695 | if (err < 0) |
5697 | return err; | 5696 | return err; |
5698 | if (err == 1) { | 5697 | if (err == 1) { |
@@ -5700,9 +5699,9 @@ static int do_check(struct bpf_verifier_env *env) | |||
5700 | if (env->log.level) { | 5699 | if (env->log.level) { |
5701 | if (do_print_state) | 5700 | if (do_print_state) |
5702 | verbose(env, "\nfrom %d to %d: safe\n", | 5701 | verbose(env, "\nfrom %d to %d: safe\n", |
5703 | prev_insn_idx, insn_idx); | 5702 | env->prev_insn_idx, env->insn_idx); |
5704 | else | 5703 | else |
5705 | verbose(env, "%d: safe\n", insn_idx); | 5704 | verbose(env, "%d: safe\n", env->insn_idx); |
5706 | } | 5705 | } |
5707 | goto process_bpf_exit; | 5706 | goto process_bpf_exit; |
5708 | } | 5707 | } |
@@ -5715,10 +5714,10 @@ static int do_check(struct bpf_verifier_env *env) | |||
5715 | 5714 | ||
5716 | if (env->log.level > 1 || (env->log.level && do_print_state)) { | 5715 | if (env->log.level > 1 || (env->log.level && do_print_state)) { |
5717 | if (env->log.level > 1) | 5716 | if (env->log.level > 1) |
5718 | verbose(env, "%d:", insn_idx); | 5717 | verbose(env, "%d:", env->insn_idx); |
5719 | else | 5718 | else |
5720 | verbose(env, "\nfrom %d to %d:", | 5719 | verbose(env, "\nfrom %d to %d:", |
5721 | prev_insn_idx, insn_idx); | 5720 | env->prev_insn_idx, env->insn_idx); |
5722 | print_verifier_state(env, state->frame[state->curframe]); | 5721 | print_verifier_state(env, state->frame[state->curframe]); |
5723 | do_print_state = false; | 5722 | do_print_state = false; |
5724 | } | 5723 | } |
@@ -5729,20 +5728,20 @@ static int do_check(struct bpf_verifier_env *env) | |||
5729 | .private_data = env, | 5728 | .private_data = env, |
5730 | }; | 5729 | }; |
5731 | 5730 | ||
5732 | verbose_linfo(env, insn_idx, "; "); | 5731 | verbose_linfo(env, env->insn_idx, "; "); |
5733 | verbose(env, "%d: ", insn_idx); | 5732 | verbose(env, "%d: ", env->insn_idx); |
5734 | print_bpf_insn(&cbs, insn, env->allow_ptr_leaks); | 5733 | print_bpf_insn(&cbs, insn, env->allow_ptr_leaks); |
5735 | } | 5734 | } |
5736 | 5735 | ||
5737 | if (bpf_prog_is_dev_bound(env->prog->aux)) { | 5736 | if (bpf_prog_is_dev_bound(env->prog->aux)) { |
5738 | err = bpf_prog_offload_verify_insn(env, insn_idx, | 5737 | err = bpf_prog_offload_verify_insn(env, env->insn_idx, |
5739 | prev_insn_idx); | 5738 | env->prev_insn_idx); |
5740 | if (err) | 5739 | if (err) |
5741 | return err; | 5740 | return err; |
5742 | } | 5741 | } |
5743 | 5742 | ||
5744 | regs = cur_regs(env); | 5743 | regs = cur_regs(env); |
5745 | env->insn_aux_data[insn_idx].seen = true; | 5744 | env->insn_aux_data[env->insn_idx].seen = true; |
5746 | 5745 | ||
5747 | if (class == BPF_ALU || class == BPF_ALU64) { | 5746 | if (class == BPF_ALU || class == BPF_ALU64) { |
5748 | err = check_alu_op(env, insn); | 5747 | err = check_alu_op(env, insn); |
@@ -5768,13 +5767,13 @@ static int do_check(struct bpf_verifier_env *env) | |||
5768 | /* check that memory (src_reg + off) is readable, | 5767 | /* check that memory (src_reg + off) is readable, |
5769 | * the state of dst_reg will be updated by this func | 5768 | * the state of dst_reg will be updated by this func |
5770 | */ | 5769 | */ |
5771 | err = check_mem_access(env, insn_idx, insn->src_reg, insn->off, | 5770 | err = check_mem_access(env, env->insn_idx, insn->src_reg, |
5772 | BPF_SIZE(insn->code), BPF_READ, | 5771 | insn->off, BPF_SIZE(insn->code), |
5773 | insn->dst_reg, false); | 5772 | BPF_READ, insn->dst_reg, false); |
5774 | if (err) | 5773 | if (err) |
5775 | return err; | 5774 | return err; |
5776 | 5775 | ||
5777 | prev_src_type = &env->insn_aux_data[insn_idx].ptr_type; | 5776 | prev_src_type = &env->insn_aux_data[env->insn_idx].ptr_type; |
5778 | 5777 | ||
5779 | if (*prev_src_type == NOT_INIT) { | 5778 | if (*prev_src_type == NOT_INIT) { |
5780 | /* saw a valid insn | 5779 | /* saw a valid insn |
@@ -5799,10 +5798,10 @@ static int do_check(struct bpf_verifier_env *env) | |||
5799 | enum bpf_reg_type *prev_dst_type, dst_reg_type; | 5798 | enum bpf_reg_type *prev_dst_type, dst_reg_type; |
5800 | 5799 | ||
5801 | if (BPF_MODE(insn->code) == BPF_XADD) { | 5800 | if (BPF_MODE(insn->code) == BPF_XADD) { |
5802 | err = check_xadd(env, insn_idx, insn); | 5801 | err = check_xadd(env, env->insn_idx, insn); |
5803 | if (err) | 5802 | if (err) |
5804 | return err; | 5803 | return err; |
5805 | insn_idx++; | 5804 | env->insn_idx++; |
5806 | continue; | 5805 | continue; |
5807 | } | 5806 | } |
5808 | 5807 | ||
@@ -5818,13 +5817,13 @@ static int do_check(struct bpf_verifier_env *env) | |||
5818 | dst_reg_type = regs[insn->dst_reg].type; | 5817 | dst_reg_type = regs[insn->dst_reg].type; |
5819 | 5818 | ||
5820 | /* check that memory (dst_reg + off) is writeable */ | 5819 | /* check that memory (dst_reg + off) is writeable */ |
5821 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 5820 | err = check_mem_access(env, env->insn_idx, insn->dst_reg, |
5822 | BPF_SIZE(insn->code), BPF_WRITE, | 5821 | insn->off, BPF_SIZE(insn->code), |
5823 | insn->src_reg, false); | 5822 | BPF_WRITE, insn->src_reg, false); |
5824 | if (err) | 5823 | if (err) |
5825 | return err; | 5824 | return err; |
5826 | 5825 | ||
5827 | prev_dst_type = &env->insn_aux_data[insn_idx].ptr_type; | 5826 | prev_dst_type = &env->insn_aux_data[env->insn_idx].ptr_type; |
5828 | 5827 | ||
5829 | if (*prev_dst_type == NOT_INIT) { | 5828 | if (*prev_dst_type == NOT_INIT) { |
5830 | *prev_dst_type = dst_reg_type; | 5829 | *prev_dst_type = dst_reg_type; |
@@ -5852,9 +5851,9 @@ static int do_check(struct bpf_verifier_env *env) | |||
5852 | } | 5851 | } |
5853 | 5852 | ||
5854 | /* check that memory (dst_reg + off) is writeable */ | 5853 | /* check that memory (dst_reg + off) is writeable */ |
5855 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 5854 | err = check_mem_access(env, env->insn_idx, insn->dst_reg, |
5856 | BPF_SIZE(insn->code), BPF_WRITE, | 5855 | insn->off, BPF_SIZE(insn->code), |
5857 | -1, false); | 5856 | BPF_WRITE, -1, false); |
5858 | if (err) | 5857 | if (err) |
5859 | return err; | 5858 | return err; |
5860 | 5859 | ||
@@ -5872,9 +5871,9 @@ static int do_check(struct bpf_verifier_env *env) | |||
5872 | } | 5871 | } |
5873 | 5872 | ||
5874 | if (insn->src_reg == BPF_PSEUDO_CALL) | 5873 | if (insn->src_reg == BPF_PSEUDO_CALL) |
5875 | err = check_func_call(env, insn, &insn_idx); | 5874 | err = check_func_call(env, insn, &env->insn_idx); |
5876 | else | 5875 | else |
5877 | err = check_helper_call(env, insn->imm, insn_idx); | 5876 | err = check_helper_call(env, insn->imm, env->insn_idx); |
5878 | if (err) | 5877 | if (err) |
5879 | return err; | 5878 | return err; |
5880 | 5879 | ||
@@ -5887,7 +5886,7 @@ static int do_check(struct bpf_verifier_env *env) | |||
5887 | return -EINVAL; | 5886 | return -EINVAL; |
5888 | } | 5887 | } |
5889 | 5888 | ||
5890 | insn_idx += insn->off + 1; | 5889 | env->insn_idx += insn->off + 1; |
5891 | continue; | 5890 | continue; |
5892 | 5891 | ||
5893 | } else if (opcode == BPF_EXIT) { | 5892 | } else if (opcode == BPF_EXIT) { |
@@ -5901,8 +5900,8 @@ static int do_check(struct bpf_verifier_env *env) | |||
5901 | 5900 | ||
5902 | if (state->curframe) { | 5901 | if (state->curframe) { |
5903 | /* exit from nested function */ | 5902 | /* exit from nested function */ |
5904 | prev_insn_idx = insn_idx; | 5903 | env->prev_insn_idx = env->insn_idx; |
5905 | err = prepare_func_exit(env, &insn_idx); | 5904 | err = prepare_func_exit(env, &env->insn_idx); |
5906 | if (err) | 5905 | if (err) |
5907 | return err; | 5906 | return err; |
5908 | do_print_state = true; | 5907 | do_print_state = true; |
@@ -5932,7 +5931,8 @@ static int do_check(struct bpf_verifier_env *env) | |||
5932 | if (err) | 5931 | if (err) |
5933 | return err; | 5932 | return err; |
5934 | process_bpf_exit: | 5933 | process_bpf_exit: |
5935 | err = pop_stack(env, &prev_insn_idx, &insn_idx); | 5934 | err = pop_stack(env, &env->prev_insn_idx, |
5935 | &env->insn_idx); | ||
5936 | if (err < 0) { | 5936 | if (err < 0) { |
5937 | if (err != -ENOENT) | 5937 | if (err != -ENOENT) |
5938 | return err; | 5938 | return err; |
@@ -5942,7 +5942,7 @@ process_bpf_exit: | |||
5942 | continue; | 5942 | continue; |
5943 | } | 5943 | } |
5944 | } else { | 5944 | } else { |
5945 | err = check_cond_jmp_op(env, insn, &insn_idx); | 5945 | err = check_cond_jmp_op(env, insn, &env->insn_idx); |
5946 | if (err) | 5946 | if (err) |
5947 | return err; | 5947 | return err; |
5948 | } | 5948 | } |
@@ -5959,8 +5959,8 @@ process_bpf_exit: | |||
5959 | if (err) | 5959 | if (err) |
5960 | return err; | 5960 | return err; |
5961 | 5961 | ||
5962 | insn_idx++; | 5962 | env->insn_idx++; |
5963 | env->insn_aux_data[insn_idx].seen = true; | 5963 | env->insn_aux_data[env->insn_idx].seen = true; |
5964 | } else { | 5964 | } else { |
5965 | verbose(env, "invalid BPF_LD mode\n"); | 5965 | verbose(env, "invalid BPF_LD mode\n"); |
5966 | return -EINVAL; | 5966 | return -EINVAL; |
@@ -5970,7 +5970,7 @@ process_bpf_exit: | |||
5970 | return -EINVAL; | 5970 | return -EINVAL; |
5971 | } | 5971 | } |
5972 | 5972 | ||
5973 | insn_idx++; | 5973 | env->insn_idx++; |
5974 | } | 5974 | } |
5975 | 5975 | ||
5976 | verbose(env, "processed %d insns (limit %d), stack depth ", | 5976 | verbose(env, "processed %d insns (limit %d), stack depth ", |