diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.9.21/0042-bpf-adjust-insn_aux_data-when-patching-insns.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.9.21/0042-bpf-adjust-insn_aux_data-when-patching-insns.patch | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.9.21/0042-bpf-adjust-insn_aux_data-when-patching-insns.patch b/common/recipes-kernel/linux/linux-yocto-4.9.21/0042-bpf-adjust-insn_aux_data-when-patching-insns.patch new file mode 100644 index 00000000..f6ce7d86 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.9.21/0042-bpf-adjust-insn_aux_data-when-patching-insns.patch @@ -0,0 +1,103 @@ +From cf7ad5027cb0764ea5276a432a9a3a402d2a2034 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann <daniel@iogearbox.net> +Date: Fri, 22 Dec 2017 16:29:02 +0100 +Subject: [PATCH 042/103] bpf: adjust insn_aux_data when patching insns + +From: Alexei Starovoitov <ast@fb.com> + +[ Upstream commit 8041902dae5299c1f194ba42d14383f734631009 ] + +convert_ctx_accesses() replaces single bpf instruction with a set of +instructions. Adjust corresponding insn_aux_data while patching. +It's needed to make sure subsequent 'for(all insn)' loops +have matching insn and insn_aux_data. + +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Acked-by: Daniel Borkmann <daniel@iogearbox.net> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/bpf/verifier.c | 44 +++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 39 insertions(+), 5 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 85d1c94..66ee0c4 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -3017,6 +3017,41 @@ static void convert_pseudo_ld_imm64(struct bpf_verifier_env *env) + insn->src_reg = 0; + } + ++/* single env->prog->insni[off] instruction was replaced with the range ++ * insni[off, off + cnt). Adjust corresponding insn_aux_data by copying ++ * [0, off) and [off, end) to new locations, so the patched range stays zero ++ */ ++static int adjust_insn_aux_data(struct bpf_verifier_env *env, u32 prog_len, ++ u32 off, u32 cnt) ++{ ++ struct bpf_insn_aux_data *new_data, *old_data = env->insn_aux_data; ++ ++ if (cnt == 1) ++ return 0; ++ new_data = vzalloc(sizeof(struct bpf_insn_aux_data) * prog_len); ++ if (!new_data) ++ return -ENOMEM; ++ memcpy(new_data, old_data, sizeof(struct bpf_insn_aux_data) * off); ++ memcpy(new_data + off + cnt - 1, old_data + off, ++ sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1)); ++ env->insn_aux_data = new_data; ++ vfree(old_data); ++ return 0; ++} ++ ++static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off, ++ const struct bpf_insn *patch, u32 len) ++{ ++ struct bpf_prog *new_prog; ++ ++ new_prog = bpf_patch_insn_single(env->prog, off, patch, len); ++ if (!new_prog) ++ return NULL; ++ if (adjust_insn_aux_data(env, new_prog->len, off, len)) ++ return NULL; ++ return new_prog; ++} ++ + /* convert load instructions that access fields of 'struct __sk_buff' + * into sequence of instructions that access fields of 'struct sk_buff' + */ +@@ -3036,10 +3071,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + verbose("bpf verifier is misconfigured\n"); + return -EINVAL; + } else if (cnt) { +- new_prog = bpf_patch_insn_single(env->prog, 0, +- insn_buf, cnt); ++ new_prog = bpf_patch_insn_data(env, 0, insn_buf, cnt); + if (!new_prog) + return -ENOMEM; ++ + env->prog = new_prog; + delta += cnt - 1; + } +@@ -3060,7 +3095,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + else + continue; + +- if (env->insn_aux_data[i].ptr_type != PTR_TO_CTX) ++ if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX) + continue; + + cnt = ops->convert_ctx_access(type, insn->dst_reg, insn->src_reg, +@@ -3070,8 +3105,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + return -EINVAL; + } + +- new_prog = bpf_patch_insn_single(env->prog, i + delta, insn_buf, +- cnt); ++ new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); + if (!new_prog) + return -ENOMEM; + +-- +2.7.4 + |