@@ -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)
This patch migrate fixup_bpf_calls to new list patching infrastructure. Signed-off-by: Jiong Wang <jiong.wang@netronome.com> --- kernel/bpf/verifier.c | 94 +++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 45 deletions(-)