This patch migrate fixup_bpf_calls to new list patching infrastructure. Signed-off-by: Jiong Wang <jiong.wang@xxxxxxxxxxxxx> --- kernel/bpf/verifier.c | 94 +++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2d16e85..30ed28e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9033,16 +9033,19 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) { struct bpf_prog *prog = env->prog; struct bpf_insn *insn = prog->insnsi; + struct bpf_list_insn *list, *elem; const struct bpf_func_proto *fn; - const int insn_cnt = prog->len; const struct bpf_map_ops *ops; struct bpf_insn_aux_data *aux; struct bpf_insn insn_buf[16]; - struct bpf_prog *new_prog; struct bpf_map *map_ptr; - int i, cnt, delta = 0; + int cnt, ret = 0; - for (i = 0; i < insn_cnt; i++, insn++) { + list = bpf_create_list_insn(env->prog); + if (IS_ERR(list)) + return PTR_ERR(list); + for (elem = list; elem; elem = elem->next) { + insn = &elem->insn; if (insn->code == (BPF_ALU64 | BPF_MOD | BPF_X) || insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) || insn->code == (BPF_ALU | BPF_MOD | BPF_X) || @@ -9073,13 +9076,11 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) cnt = ARRAY_SIZE(mask_and_mod) - (is64 ? 1 : 0); } - new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt); - if (!new_prog) - return -ENOMEM; - - delta += cnt - 1; - env->prog = prog = new_prog; - insn = new_prog->insnsi + i + delta; + elem = bpf_patch_list_insn(elem, patchlet, cnt); + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + goto free_list_ret; + } continue; } @@ -9089,16 +9090,15 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) cnt = env->ops->gen_ld_abs(insn, insn_buf); if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) { verbose(env, "bpf verifier is misconfigured\n"); - return -EINVAL; + ret = -EINVAL; + goto free_list_ret; } - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); - if (!new_prog) - return -ENOMEM; - - delta += cnt - 1; - env->prog = prog = new_prog; - insn = new_prog->insnsi + i + delta; + elem = bpf_patch_list_insn(elem, insn_buf, cnt); + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + goto free_list_ret; + } continue; } @@ -9111,7 +9111,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) bool issrc, isneg; u32 off_reg; - aux = &env->insn_aux_data[i + delta]; + aux = &env->insn_aux_data[elem->orig_idx - 1]; if (!aux->alu_state || aux->alu_state == BPF_ALU_NON_POINTER) continue; @@ -9144,13 +9144,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1); cnt = patch - insn_buf; - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); - if (!new_prog) - return -ENOMEM; + elem = bpf_patch_list_insn(elem, insn_buf, cnt); + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + goto free_list_ret; + } - delta += cnt - 1; - env->prog = prog = new_prog; - insn = new_prog->insnsi + i + delta; continue; } @@ -9183,7 +9182,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) insn->imm = 0; insn->code = BPF_JMP | BPF_TAIL_CALL; - aux = &env->insn_aux_data[i + delta]; + aux = &env->insn_aux_data[elem->orig_idx - 1]; if (!bpf_map_ptr_unpriv(aux)) continue; @@ -9195,7 +9194,8 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) */ if (bpf_map_ptr_poisoned(aux)) { verbose(env, "tail_call abusing map_ptr\n"); - return -EINVAL; + ret = -EINVAL; + goto free_list_ret; } map_ptr = BPF_MAP_PTR(aux->map_state); @@ -9207,13 +9207,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) map)->index_mask); insn_buf[2] = *insn; cnt = 3; - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); - if (!new_prog) - return -ENOMEM; + elem = bpf_patch_list_insn(elem, insn_buf, cnt); + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + goto free_list_ret; + } - delta += cnt - 1; - env->prog = prog = new_prog; - insn = new_prog->insnsi + i + delta; continue; } @@ -9228,7 +9227,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) insn->imm == BPF_FUNC_map_push_elem || insn->imm == BPF_FUNC_map_pop_elem || insn->imm == BPF_FUNC_map_peek_elem)) { - aux = &env->insn_aux_data[i + delta]; + aux = &env->insn_aux_data[elem->orig_idx - 1]; if (bpf_map_ptr_poisoned(aux)) goto patch_call_imm; @@ -9239,17 +9238,16 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) cnt = ops->map_gen_lookup(map_ptr, insn_buf); if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) { verbose(env, "bpf verifier is misconfigured\n"); - return -EINVAL; + ret = -EINVAL; + goto free_list_ret; } - new_prog = bpf_patch_insn_data(env, i + delta, - insn_buf, cnt); - if (!new_prog) - return -ENOMEM; + elem = bpf_patch_list_insn(elem, insn_buf, cnt); + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + goto free_list_ret; + } - delta += cnt - 1; - env->prog = prog = new_prog; - insn = new_prog->insnsi + i + delta; continue; } @@ -9307,12 +9305,18 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) verbose(env, "kernel subsystem misconfigured func %s#%d\n", func_id_name(insn->imm), insn->imm); - return -EFAULT; + ret = -EFAULT; + goto free_list_ret; } insn->imm = fn->func - __bpf_call_base; } - return 0; + env = verifier_linearize_list_insn(env, list); + if (IS_ERR(env)) + ret = PTR_ERR(env); +free_list_ret: + bpf_destroy_list_insn(list); + return ret; } static void free_states(struct bpf_verifier_env *env) -- 2.7.4