4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Alexei Starovoitov <a...@fb.com>

commit 79741b3bdec01a8628368fbcfccc7d189ed606cb upstream.

reduce indent and make it iterate over instructions similar to
convert_ctx_accesses(). Also convert hard BUG_ON into soft verifier error.

Signed-off-by: Alexei Starovoitov <a...@kernel.org>
Acked-by: Daniel Borkmann <dan...@iogearbox.net>
Signed-off-by: David S. Miller <da...@davemloft.net>
Cc: Jiri Slaby <jsl...@suse.cz>
[Backported to 4.9.y - gregkh]
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 kernel/bpf/verifier.c |   75 +++++++++++++++++++++++---------------------------
 1 file changed, 35 insertions(+), 40 deletions(-)

--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3362,55 +3362,50 @@ static int convert_ctx_accesses(struct b
        return 0;
 }
 
-/* fixup insn->imm field of bpf_call instructions:
- * if (insn->imm == BPF_FUNC_map_lookup_elem)
- *      insn->imm = bpf_map_lookup_elem - __bpf_call_base;
- * else if (insn->imm == BPF_FUNC_map_update_elem)
- *      insn->imm = bpf_map_update_elem - __bpf_call_base;
- * else ...
+/* fixup insn->imm field of bpf_call instructions
  *
  * this function is called after eBPF program passed verification
  */
-static void fixup_bpf_calls(struct bpf_prog *prog)
+static int fixup_bpf_calls(struct bpf_verifier_env *env)
 {
+       struct bpf_prog *prog = env->prog;
+       struct bpf_insn *insn = prog->insnsi;
        const struct bpf_func_proto *fn;
+       const int insn_cnt = prog->len;
        int i;
 
-       for (i = 0; i < prog->len; i++) {
-               struct bpf_insn *insn = &prog->insnsi[i];
-
-               if (insn->code == (BPF_JMP | BPF_CALL)) {
-                       /* we reach here when program has bpf_call instructions
-                        * and it passed bpf_check(), means that
-                        * ops->get_func_proto must have been supplied, check it
-                        */
-                       BUG_ON(!prog->aux->ops->get_func_proto);
-
-                       if (insn->imm == BPF_FUNC_get_route_realm)
-                               prog->dst_needed = 1;
-                       if (insn->imm == BPF_FUNC_get_prandom_u32)
-                               bpf_user_rnd_init_once();
-                       if (insn->imm == BPF_FUNC_tail_call) {
-                               /* mark bpf_tail_call as different opcode
-                                * to avoid conditional branch in
-                                * interpeter for every normal call
-                                * and to prevent accidental JITing by
-                                * JIT compiler that doesn't support
-                                * bpf_tail_call yet
-                                */
-                               insn->imm = 0;
-                               insn->code |= BPF_X;
-                               continue;
-                       }
+       for (i = 0; i < insn_cnt; i++, insn++) {
+               if (insn->code != (BPF_JMP | BPF_CALL))
+                       continue;
+
+               if (insn->imm == BPF_FUNC_get_route_realm)
+                       prog->dst_needed = 1;
+               if (insn->imm == BPF_FUNC_get_prandom_u32)
+                       bpf_user_rnd_init_once();
+               if (insn->imm == BPF_FUNC_tail_call) {
+                       /* mark bpf_tail_call as different opcode to avoid
+                        * conditional branch in the interpeter for every normal
+                        * call and to prevent accidental JITing by JIT compiler
+                        * that doesn't support bpf_tail_call yet
+                        */
+                       insn->imm = 0;
+                       insn->code |= BPF_X;
+                       continue;
+               }
 
-                       fn = prog->aux->ops->get_func_proto(insn->imm);
-                       /* all functions that have prototype and verifier 
allowed
-                        * programs to call them, must be real in-kernel 
functions
-                        */
-                       BUG_ON(!fn->func);
-                       insn->imm = fn->func - __bpf_call_base;
+               fn = prog->aux->ops->get_func_proto(insn->imm);
+               /* all functions that have prototype and verifier allowed
+                * programs to call them, must be real in-kernel functions
+                */
+               if (!fn->func) {
+                       verbose("kernel subsystem misconfigured func %d\n",
+                               insn->imm);
+                       return -EFAULT;
                }
+               insn->imm = fn->func - __bpf_call_base;
        }
+
+       return 0;
 }
 
 static void free_states(struct bpf_verifier_env *env)
@@ -3515,7 +3510,7 @@ skip_full_check:
                ret = convert_ctx_accesses(env);
 
        if (ret == 0)
-               fixup_bpf_calls(env->prog);
+               ret = fixup_bpf_calls(env);
 
        if (log_level && log_len >= log_size - 1) {
                BUG_ON(log_len >= log_size);


Reply via email to