bpf: remove the verifier ops from program structure
authorJakub Kicinski <jakub.kicinski@netronome.com>
Mon, 16 Oct 2017 23:40:54 +0000 (16:40 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Oct 2017 13:17:10 +0000 (14:17 +0100)
Since the verifier ops don't have to be associated with
the program for its entire lifetime we can move it to
verifier's struct bpf_verifier_env.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/bpf.h
include/linux/bpf_verifier.h
kernel/bpf/syscall.c
kernel/bpf/verifier.c

index e1fba5504ca596f38f6e5b1e2507716a30d641ce..cf91977e87196e2f90f34660f794223b9cb790c7 100644 (file)
@@ -188,7 +188,6 @@ struct bpf_prog_aux {
        struct latch_tree_node ksym_tnode;
        struct list_head ksym_lnode;
        const struct bpf_prog_ops *ops;
-       const struct bpf_verifier_ops *vops;
        struct bpf_map **used_maps;
        struct bpf_prog *prog;
        struct user_struct *user;
index f00ef751c1c5290c0c62a04bcfb9dcc6d4ae606c..feeaea93d959fc738afdf0f8e0ca0719eb4f542d 100644 (file)
@@ -141,6 +141,7 @@ struct bpf_ext_analyzer_ops {
  */
 struct bpf_verifier_env {
        struct bpf_prog *prog;          /* eBPF program being verified */
+       const struct bpf_verifier_ops *ops;
        struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
        int stack_size;                 /* number of states to be processed */
        bool strict_alignment;          /* perform strict pointer alignment checks */
index 444902b5a30dad15da907fa71056fd4a98a7e781..0e893cac6795ce27d82bd1d2e29827d5abcff0a3 100644 (file)
@@ -748,22 +748,12 @@ static const struct bpf_prog_ops * const bpf_prog_types[] = {
 #undef BPF_MAP_TYPE
 };
 
-static const struct bpf_verifier_ops * const bpf_verifier_ops[] = {
-#define BPF_PROG_TYPE(_id, _name) \
-       [_id] = & _name ## _verifier_ops,
-#define BPF_MAP_TYPE(_id, _ops)
-#include <linux/bpf_types.h>
-#undef BPF_PROG_TYPE
-#undef BPF_MAP_TYPE
-};
-
 static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
 {
        if (type >= ARRAY_SIZE(bpf_prog_types) || !bpf_prog_types[type])
                return -EINVAL;
 
        prog->aux->ops = bpf_prog_types[type];
-       prog->aux->vops = bpf_verifier_ops[type];
        prog->type = type;
        return 0;
 }
index 38e24d69fc9554583e7ae57840b2bb699b80e0a8..3b6e2c550e96d65f8a4c0f28a4a3d2a2a8710161 100644 (file)
 
 #include "disasm.h"
 
+static const struct bpf_verifier_ops * const bpf_verifier_ops[] = {
+#define BPF_PROG_TYPE(_id, _name) \
+       [_id] = & _name ## _verifier_ops,
+#define BPF_MAP_TYPE(_id, _ops)
+#include <linux/bpf_types.h>
+#undef BPF_PROG_TYPE
+#undef BPF_MAP_TYPE
+};
+
 /* bpf_check() is a static code analyzer that walks eBPF program
  * instruction by instruction and updates register/stack state.
  * All paths of conditional branches are analyzed until 'bpf_exit' insn.
@@ -856,8 +865,8 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
                        *reg_type = info.reg_type;
                        return 0;
                }
-       } else if (env->prog->aux->vops->is_valid_access &&
-                  env->prog->aux->vops->is_valid_access(off, size, t, &info)) {
+       } else if (env->ops->is_valid_access &&
+                  env->ops->is_valid_access(off, size, t, &info)) {
                /* A non zero info.ctx_field_size indicates that this field is a
                 * candidate for later verifier transformation to load the whole
                 * field and then apply a mask when accessed with a narrower
@@ -1565,8 +1574,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
                return -EINVAL;
        }
 
-       if (env->prog->aux->vops->get_func_proto)
-               fn = env->prog->aux->vops->get_func_proto(func_id);
+       if (env->ops->get_func_proto)
+               fn = env->ops->get_func_proto(func_id);
 
        if (!fn) {
                verbose(env, "unknown func %s#%d\n", func_id_name(func_id),
@@ -4035,7 +4044,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
  */
 static int convert_ctx_accesses(struct bpf_verifier_env *env)
 {
-       const struct bpf_verifier_ops *ops = env->prog->aux->vops;
+       const struct bpf_verifier_ops *ops = env->ops;
        int i, cnt, size, ctx_field_size, delta = 0;
        const int insn_cnt = env->prog->len;
        struct bpf_insn insn_buf[16], *insn;
@@ -4236,7 +4245,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                        insn      = new_prog->insnsi + i + delta;
                }
 patch_call_imm:
-               fn = prog->aux->vops->get_func_proto(insn->imm);
+               fn = env->ops->get_func_proto(insn->imm);
                /* all functions that have prototype and verifier allowed
                 * programs to call them, must be real in-kernel functions
                 */
@@ -4294,6 +4303,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
        if (!env->insn_aux_data)
                goto err_free_env;
        env->prog = *prog;
+       env->ops = bpf_verifier_ops[env->prog->type];
 
        /* grab the mutex to protect few globals used by verifier */
        mutex_lock(&bpf_verifier_lock);
@@ -4406,6 +4416,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
        if (!env->insn_aux_data)
                goto err_free_env;
        env->prog = prog;
+       env->ops = bpf_verifier_ops[env->prog->type];
        env->analyzer_ops = ops;
        env->analyzer_priv = priv;