OSDN Git Service

bpf: move fixup_bpf_calls() function
authorAlexei Starovoitov <ast@fb.com>
Thu, 16 Mar 2017 01:26:39 +0000 (18:26 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Jan 2018 08:35:30 +0000 (09:35 +0100)
commit e245c5c6a5656e4d61aa7bb08e9694fd6e5b2b9d upstream.

no functional change.
move fixup_bpf_calls() to verifier.c
it's being refactored in the next patch

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: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/bpf/syscall.c
kernel/bpf/verifier.c

index 4e32cc9..424accd 100644 (file)
@@ -447,57 +447,6 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl)
        list_add(&tl->list_node, &bpf_prog_types);
 }
 
-/* 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 ...
- *
- * this function is called after eBPF program passed verification
- */
-static void fixup_bpf_calls(struct bpf_prog *prog)
-{
-       const struct bpf_func_proto *fn;
-       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;
-                       }
-
-                       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;
-               }
-       }
-}
-
 /* drop refcnt on maps used by eBPF program and free auxilary data */
 static void free_used_maps(struct bpf_prog_aux *aux)
 {
@@ -680,9 +629,6 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (err < 0)
                goto free_used_maps;
 
-       /* fixup BPF_CALL->imm field */
-       fixup_bpf_calls(prog);
-
        /* eBPF program is ready to be JITed */
        err = bpf_prog_select_runtime(prog);
        if (err < 0)
index 769d2ec..198737d 100644 (file)
@@ -2158,6 +2158,58 @@ static int convert_ctx_accesses(struct verifier_env *env)
        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 ...
+ *
+ * this function is called after eBPF program passed verification
+ */
+static void fixup_bpf_calls(struct bpf_prog *prog)
+{
+       const struct bpf_func_proto *fn;
+       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;
+                       }
+
+                       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;
+               }
+       }
+}
+
+
 static void free_states(struct verifier_env *env)
 {
        struct verifier_state_list *sl, *sln;
@@ -2256,6 +2308,9 @@ skip_full_check:
                /* program is valid, convert *(u32*)(ctx + off) accesses */
                ret = convert_ctx_accesses(env);
 
+       if (ret == 0)
+               fixup_bpf_calls(env->prog);
+
        if (log_level && log_len >= log_size - 1) {
                BUG_ON(log_len >= log_size);
                /* verifier log exceeded user supplied buffer */