diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/verifier.c | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 47bb3eee950c..198737d36754 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2158,52 +2158,58 @@ static int convert_ctx_accesses(struct verifier_env *env) return 0; } -/* fixup insn->imm field of bpf_call instructions +/* fixup insn->imm field of bpf_call instructions: + * if (insn->imm == BPF_FUNC_map_lookup_elem) + * insn->imm = bpf_map_lookup_elem - __bpf_call_base; + * else if (insn->imm == BPF_FUNC_map_update_elem) + * insn->imm = bpf_map_update_elem - __bpf_call_base; + * else ... * * this function is called after eBPF program passed verification */ -static int fixup_bpf_calls(struct verifier_env *env) +static void fixup_bpf_calls(struct bpf_prog *prog) { - struct bpf_prog *prog = env->prog; - struct bpf_insn *insn = prog->insnsi; const struct bpf_func_proto *fn; - const int insn_cnt = prog->len; int i; - for (i = 0; i < insn_cnt; i++, insn++) { - if (insn->code != (BPF_JMP | BPF_CALL)) - continue; + for (i = 0; i < prog->len; i++) { + struct bpf_insn *insn = &prog->insnsi[i]; - if (insn->imm == BPF_FUNC_get_route_realm) - prog->dst_needed = 1; - if (insn->imm == BPF_FUNC_get_prandom_u32) - bpf_user_rnd_init_once(); - if (insn->imm == BPF_FUNC_tail_call) { - /* mark bpf_tail_call as different opcode to avoid - * conditional branch in the interpeter for every normal - * call and to prevent accidental JITing by JIT compiler - * that doesn't support bpf_tail_call yet + if (insn->code == (BPF_JMP | BPF_CALL)) { + /* we reach here when program has bpf_call instructions + * and it passed bpf_check(), means that + * ops->get_func_proto must have been supplied, check it */ - insn->imm = 0; - insn->code |= BPF_X; - continue; - } + BUG_ON(!prog->aux->ops->get_func_proto); + + if (insn->imm == BPF_FUNC_get_route_realm) + prog->dst_needed = 1; + if (insn->imm == BPF_FUNC_get_prandom_u32) + bpf_user_rnd_init_once(); + if (insn->imm == BPF_FUNC_tail_call) { + /* mark bpf_tail_call as different opcode + * to avoid conditional branch in + * interpeter for every normal call + * and to prevent accidental JITing by + * JIT compiler that doesn't support + * bpf_tail_call yet + */ + insn->imm = 0; + insn->code |= BPF_X; + continue; + } - fn = prog->aux->ops->get_func_proto(insn->imm); - /* all functions that have prototype and verifier allowed - * programs to call them, must be real in-kernel functions - */ - if (!fn->func) { - verbose("kernel subsystem misconfigured func %d\n", - insn->imm); - return -EFAULT; + fn = prog->aux->ops->get_func_proto(insn->imm); + /* all functions that have prototype and verifier allowed + * programs to call them, must be real in-kernel functions + */ + BUG_ON(!fn->func); + insn->imm = fn->func - __bpf_call_base; } - insn->imm = fn->func - __bpf_call_base; } - - return 0; } + static void free_states(struct verifier_env *env) { struct verifier_state_list *sl, *sln; @@ -2303,7 +2309,7 @@ skip_full_check: ret = convert_ctx_accesses(env); if (ret == 0) - ret = fixup_bpf_calls(env); + fixup_bpf_calls(env->prog); if (log_level && log_len >= log_size - 1) { BUG_ON(log_len >= log_size); |
