]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - kernel/bpf/verifier.c
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-bionic-kernel.git] / kernel / bpf / verifier.c
index d690c7dd1f1a53dd07752308c234f5f7ac44d724..799b2451ef2df42b17aadfe679a09dee9a0848c9 100644 (file)
@@ -2292,7 +2292,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        }
                } else {
                        if (insn->src_reg != BPF_REG_0 || insn->off != 0 ||
-                           (insn->imm != 16 && insn->imm != 32 && insn->imm != 64)) {
+                           (insn->imm != 16 && insn->imm != 32 && insn->imm != 64) ||
+                           BPF_CLASS(insn->code) == BPF_ALU64) {
                                verbose("BPF_END uses reserved fields\n");
                                return -EINVAL;
                        }
@@ -4203,6 +4204,22 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                        continue;
                }
 
+               if (insn->imm == BPF_FUNC_redirect_map) {
+                       u64 addr = (unsigned long)prog;
+                       struct bpf_insn r4_ld[] = {
+                               BPF_LD_IMM64(BPF_REG_4, addr),
+                               *insn,
+                       };
+                       cnt = ARRAY_SIZE(r4_ld);
+
+                       new_prog = bpf_patch_insn_data(env, i + delta, r4_ld, cnt);
+                       if (!new_prog)
+                               return -ENOMEM;
+
+                       delta    += cnt - 1;
+                       env->prog = prog = new_prog;
+                       insn      = new_prog->insnsi + i + delta;
+               }
 patch_call_imm:
                fn = prog->aux->ops->get_func_proto(insn->imm);
                /* all functions that have prototype and verifier allowed