diff options
| author | Alexei Starovoitov <ast@fb.com> | 2017-03-15 21:26:40 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-03-16 23:44:11 -0400 |
| commit | 79741b3bdec01a8628368fbcfccc7d189ed606cb (patch) | |
| tree | 8c8e866e58087e26eab10b1086282a73dfcdcf86 /kernel | |
| parent | e245c5c6a5656e4d61aa7bb08e9694fd6e5b2b9d (diff) | |
bpf: refactor fixup_bpf_calls()
reduce indent and make it iterate over instructions similar to
convert_ctx_accesses(). Also convert hard BUG_ON into soft verifier error.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/verifier.c | 76 |
1 files changed, 35 insertions, 41 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e41da6c57053..5dfa9b8111da 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
| @@ -3233,59 +3233,53 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) | |||
| 3233 | return 0; | 3233 | return 0; |
| 3234 | } | 3234 | } |
| 3235 | 3235 | ||
| 3236 | /* fixup insn->imm field of bpf_call instructions: | 3236 | /* fixup insn->imm field of bpf_call instructions |
| 3237 | * if (insn->imm == BPF_FUNC_map_lookup_elem) | ||
| 3238 | * insn->imm = bpf_map_lookup_elem - __bpf_call_base; | ||
| 3239 | * else if (insn->imm == BPF_FUNC_map_update_elem) | ||
| 3240 | * insn->imm = bpf_map_update_elem - __bpf_call_base; | ||
| 3241 | * else ... | ||
| 3242 | * | 3237 | * |
| 3243 | * this function is called after eBPF program passed verification | 3238 | * this function is called after eBPF program passed verification |
| 3244 | */ | 3239 | */ |
| 3245 | static void fixup_bpf_calls(struct bpf_prog *prog) | 3240 | static int fixup_bpf_calls(struct bpf_verifier_env *env) |
| 3246 | { | 3241 | { |
| 3242 | struct bpf_prog *prog = env->prog; | ||
| 3243 | struct bpf_insn *insn = prog->insnsi; | ||
| 3247 | const struct bpf_func_proto *fn; | 3244 | const struct bpf_func_proto *fn; |
| 3245 | const int insn_cnt = prog->len; | ||
| 3248 | int i; | 3246 | int i; |
| 3249 | 3247 | ||
| 3250 | for (i = 0; i < prog->len; i++) { | 3248 | for (i = 0; i < insn_cnt; i++, insn++) { |
| 3251 | struct bpf_insn *insn = &prog->insnsi[i]; | 3249 | if (insn->code != (BPF_JMP | BPF_CALL)) |
| 3250 | continue; | ||
| 3252 | 3251 | ||
| 3253 | if (insn->code == (BPF_JMP | BPF_CALL)) { | 3252 | if (insn->imm == BPF_FUNC_get_route_realm) |
| 3254 | /* we reach here when program has bpf_call instructions | 3253 | prog->dst_needed = 1; |
| 3255 | * and it passed bpf_check(), means that | 3254 | if (insn->imm == BPF_FUNC_get_prandom_u32) |
| 3256 | * ops->get_func_proto must have been supplied, check it | 3255 | bpf_user_rnd_init_once(); |
| 3256 | if (insn->imm == BPF_FUNC_xdp_adjust_head) | ||
| 3257 | prog->xdp_adjust_head = 1; | ||
| 3258 | if (insn->imm == BPF_FUNC_tail_call) { | ||
| 3259 | /* mark bpf_tail_call as different opcode to avoid | ||
| 3260 | * conditional branch in the interpeter for every normal | ||
| 3261 | * call and to prevent accidental JITing by JIT compiler | ||
| 3262 | * that doesn't support bpf_tail_call yet | ||
| 3257 | */ | 3263 | */ |
| 3258 | BUG_ON(!prog->aux->ops->get_func_proto); | 3264 | insn->imm = 0; |
| 3259 | 3265 | insn->code |= BPF_X; | |
| 3260 | if (insn->imm == BPF_FUNC_get_route_realm) | 3266 | continue; |
| 3261 | prog->dst_needed = 1; | 3267 | } |
| 3262 | if (insn->imm == BPF_FUNC_get_prandom_u32) | ||
| 3263 | bpf_user_rnd_init_once(); | ||
| 3264 | if (insn->imm == BPF_FUNC_xdp_adjust_head) | ||
| 3265 | prog->xdp_adjust_head = 1; | ||
| 3266 | if (insn->imm == BPF_FUNC_tail_call) { | ||
| 3267 | /* mark bpf_tail_call as different opcode | ||
| 3268 | * to avoid conditional branch in | ||
| 3269 | * interpeter for every normal call | ||
| 3270 | * and to prevent accidental JITing by | ||
| 3271 | * JIT compiler that doesn't support | ||
| 3272 | * bpf_tail_call yet | ||
| 3273 | */ | ||
| 3274 | insn->imm = 0; | ||
| 3275 | insn->code |= BPF_X; | ||
| 3276 | continue; | ||
| 3277 | } | ||
| 3278 | 3268 | ||
| 3279 | fn = prog->aux->ops->get_func_proto(insn->imm); | 3269 | fn = prog->aux->ops->get_func_proto(insn->imm); |
| 3280 | /* all functions that have prototype and verifier allowed | 3270 | /* all functions that have prototype and verifier allowed |
| 3281 | * programs to call them, must be real in-kernel functions | 3271 | * programs to call them, must be real in-kernel functions |
| 3282 | */ | 3272 | */ |
| 3283 | BUG_ON(!fn->func); | 3273 | if (!fn->func) { |
| 3284 | insn->imm = fn->func - __bpf_call_base; | 3274 | verbose("kernel subsystem misconfigured func %s#%d\n", |
| 3275 | func_id_name(insn->imm), insn->imm); | ||
| 3276 | return -EFAULT; | ||
| 3285 | } | 3277 | } |
| 3278 | insn->imm = fn->func - __bpf_call_base; | ||
| 3286 | } | 3279 | } |
| 3287 | } | ||
| 3288 | 3280 | ||
| 3281 | return 0; | ||
| 3282 | } | ||
| 3289 | 3283 | ||
| 3290 | static void free_states(struct bpf_verifier_env *env) | 3284 | static void free_states(struct bpf_verifier_env *env) |
| 3291 | { | 3285 | { |
| @@ -3383,7 +3377,7 @@ skip_full_check: | |||
| 3383 | ret = convert_ctx_accesses(env); | 3377 | ret = convert_ctx_accesses(env); |
| 3384 | 3378 | ||
| 3385 | if (ret == 0) | 3379 | if (ret == 0) |
| 3386 | fixup_bpf_calls(env->prog); | 3380 | ret = fixup_bpf_calls(env); |
| 3387 | 3381 | ||
| 3388 | if (log_level && log_len >= log_size - 1) { | 3382 | if (log_level && log_len >= log_size - 1) { |
| 3389 | BUG_ON(log_len >= log_size); | 3383 | BUG_ON(log_len >= log_size); |
