| @@ -15439,15 +15439,16 @@ static int visit_func_call_insn(int t, struct bpf_insn *insns, · 15438 unmodified lines |
| 15439 | struct bpf_verifier_env *env, | 15439 | struct bpf_verifier_env *env, |
| 15440 | bool visit_callee) | 15440 | bool visit_callee) |
| 15441 | { | 15441 | { |
| 15442 | int ret; | 15442 | int ret, insn_sz; |
| 15443 | | 15443 | |
| 15444 | ret = push_insn(t, t + 1, FALLTHROUGH, env, false); | 15444 | insn_sz = bpf_is_ldimm64(&insns[t]) ? 2 : 1; |
| | 15445 | ret = push_insn(t, t + insn_sz, FALLTHROUGH, env, false); |
| 15445 | if (ret) | 15446 | if (ret) |
| 15446 | return ret; | 15447 | return ret; |
| 15447 | | 15448 | |
| 15448 | mark_prune_point(env, t + 1); | 15449 | mark_prune_point(env, t + insn_sz); |
| 15449 | /* when we exit from subprog, we need to record non-linear history */ | 15450 | /* when we exit from subprog, we need to record non-linear history */ |
| 15450 | mark_jmp_point(env, t + 1); | 15451 | mark_jmp_point(env, t + insn_sz); |
| 15451 | | 15452 | |
| 15452 | if (visit_callee) { | 15453 | if (visit_callee) { |
| 15453 | mark_prune_point(env, t); | 15454 | mark_prune_point(env, t); |
| @@ -15469,15 +15470,17 @@ static int visit_func_call_insn(int t, struct bpf_insn *insns, · 15 unmodified lines |
| 15469 | static int visit_insn(int t, struct bpf_verifier_env *env) | 15470 | static int visit_insn(int t, struct bpf_verifier_env *env) |
| 15470 | { | 15471 | { |
| 15471 | struct bpf_insn *insns = env->prog->insnsi, *insn = &insns[t]; | 15472 | struct bpf_insn *insns = env->prog->insnsi, *insn = &insns[t]; |
| 15472 | int ret, off; | 15473 | int ret, off, insn_sz; |
| 15473 | | 15474 | |
| 15474 | if (bpf_pseudo_func(insn)) | 15475 | if (bpf_pseudo_func(insn)) |
| 15475 | return visit_func_call_insn(t, insns, env, true); | 15476 | return visit_func_call_insn(t, insns, env, true); |
| 15476 | | 15477 | |
| 15477 | /* All non-branch instructions have a single fall-through edge. */ | 15478 | /* All non-branch instructions have a single fall-through edge. */ |
| 15478 | if (BPF_CLASS(insn->code) != BPF_JMP && | 15479 | if (BPF_CLASS(insn->code) != BPF_JMP && |
| 15479 | BPF_CLASS(insn->code) != BPF_JMP32) | 15480 | BPF_CLASS(insn->code) != BPF_JMP32) { |
| 15480 | return push_insn(t, t + 1, FALLTHROUGH, env, false); | 15481 | insn_sz = bpf_is_ldimm64(insn) ? 2 : 1; |
| | 15482 | return push_insn(t, t + insn_sz, FALLTHROUGH, env, false); |
| | 15483 | } |
| 15481 | | 15484 | |
| 15482 | switch (BPF_OP(insn->code)) { | 15485 | switch (BPF_OP(insn->code)) { |
| 15483 | case BPF_EXIT: | 15486 | case BPF_EXIT: |
| @@ -15607,11 +15610,21 @@ walk_cfg: · 123 unmodified lines |
| 15607 | } | 15610 | } |
| 15608 | | 15611 | |
| 15609 | for (i = 0; i < insn_cnt; i++) { | 15612 | for (i = 0; i < insn_cnt; i++) { |
| | 15613 | struct bpf_insn *insn = &env->prog->insnsi[i]; |
| | 15614 | |
| 15610 | if (insn_state[i] != EXPLORED) { | 15615 | if (insn_state[i] != EXPLORED) { |
| 15611 | verbose(env, "unreachable insn %d\n", i); | 15616 | verbose(env, "unreachable insn %d\n", i); |
| 15612 | ret = -EINVAL; | 15617 | ret = -EINVAL; |
| 15613 | goto err_free; | 15618 | goto err_free; |
| 15614 | } | 15619 | } |
| | 15620 | if (bpf_is_ldimm64(insn)) { |
| | 15621 | if (insn_state[i + 1] != 0) { |
| | 15622 | verbose(env, "jump into the middle of ldimm64 insn %d\n", i); |
| | 15623 | ret = -EINVAL; |
| | 15624 | goto err_free; |
| | 15625 | } |
| | 15626 | i++; /* skip second half of ldimm64 */ |
| | 15627 | } |
| 15615 | } | 15628 | } |
| 15616 | ret = 0; /* cfg looks good */ | 15629 | ret = 0; /* cfg looks good */ |
| 15617 | | 15630 | |