Commit 00176a34 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

bpf: remove the verifier ops from program structure

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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7de16e3a
...@@ -188,7 +188,6 @@ struct bpf_prog_aux { ...@@ -188,7 +188,6 @@ struct bpf_prog_aux {
struct latch_tree_node ksym_tnode; struct latch_tree_node ksym_tnode;
struct list_head ksym_lnode; struct list_head ksym_lnode;
const struct bpf_prog_ops *ops; const struct bpf_prog_ops *ops;
const struct bpf_verifier_ops *vops;
struct bpf_map **used_maps; struct bpf_map **used_maps;
struct bpf_prog *prog; struct bpf_prog *prog;
struct user_struct *user; struct user_struct *user;
......
...@@ -141,6 +141,7 @@ struct bpf_ext_analyzer_ops { ...@@ -141,6 +141,7 @@ struct bpf_ext_analyzer_ops {
*/ */
struct bpf_verifier_env { struct bpf_verifier_env {
struct bpf_prog *prog; /* eBPF program being verified */ 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 */ struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
int stack_size; /* number of states to be processed */ int stack_size; /* number of states to be processed */
bool strict_alignment; /* perform strict pointer alignment checks */ bool strict_alignment; /* perform strict pointer alignment checks */
......
...@@ -748,22 +748,12 @@ static const struct bpf_prog_ops * const bpf_prog_types[] = { ...@@ -748,22 +748,12 @@ static const struct bpf_prog_ops * const bpf_prog_types[] = {
#undef BPF_MAP_TYPE #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) 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]) if (type >= ARRAY_SIZE(bpf_prog_types) || !bpf_prog_types[type])
return -EINVAL; return -EINVAL;
prog->aux->ops = bpf_prog_types[type]; prog->aux->ops = bpf_prog_types[type];
prog->aux->vops = bpf_verifier_ops[type];
prog->type = type; prog->type = type;
return 0; return 0;
} }
......
...@@ -23,6 +23,15 @@ ...@@ -23,6 +23,15 @@
#include "disasm.h" #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 /* bpf_check() is a static code analyzer that walks eBPF program
* instruction by instruction and updates register/stack state. * instruction by instruction and updates register/stack state.
* All paths of conditional branches are analyzed until 'bpf_exit' insn. * 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, ...@@ -856,8 +865,8 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
*reg_type = info.reg_type; *reg_type = info.reg_type;
return 0; return 0;
} }
} else if (env->prog->aux->vops->is_valid_access && } else if (env->ops->is_valid_access &&
env->prog->aux->vops->is_valid_access(off, size, t, &info)) { env->ops->is_valid_access(off, size, t, &info)) {
/* A non zero info.ctx_field_size indicates that this field is a /* A non zero info.ctx_field_size indicates that this field is a
* candidate for later verifier transformation to load the whole * candidate for later verifier transformation to load the whole
* field and then apply a mask when accessed with a narrower * 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) ...@@ -1565,8 +1574,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
return -EINVAL; return -EINVAL;
} }
if (env->prog->aux->vops->get_func_proto) if (env->ops->get_func_proto)
fn = env->prog->aux->vops->get_func_proto(func_id); fn = env->ops->get_func_proto(func_id);
if (!fn) { if (!fn) {
verbose(env, "unknown func %s#%d\n", func_id_name(func_id), 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 ...@@ -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) 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; int i, cnt, size, ctx_field_size, delta = 0;
const int insn_cnt = env->prog->len; const int insn_cnt = env->prog->len;
struct bpf_insn insn_buf[16], *insn; struct bpf_insn insn_buf[16], *insn;
...@@ -4236,7 +4245,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) ...@@ -4236,7 +4245,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
insn = new_prog->insnsi + i + delta; insn = new_prog->insnsi + i + delta;
} }
patch_call_imm: 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 /* all functions that have prototype and verifier allowed
* programs to call them, must be real in-kernel functions * 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) ...@@ -4294,6 +4303,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
if (!env->insn_aux_data) if (!env->insn_aux_data)
goto err_free_env; goto err_free_env;
env->prog = *prog; env->prog = *prog;
env->ops = bpf_verifier_ops[env->prog->type];
/* grab the mutex to protect few globals used by verifier */ /* grab the mutex to protect few globals used by verifier */
mutex_lock(&bpf_verifier_lock); mutex_lock(&bpf_verifier_lock);
...@@ -4406,6 +4416,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops, ...@@ -4406,6 +4416,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
if (!env->insn_aux_data) if (!env->insn_aux_data)
goto err_free_env; goto err_free_env;
env->prog = prog; env->prog = prog;
env->ops = bpf_verifier_ops[env->prog->type];
env->analyzer_ops = ops; env->analyzer_ops = ops;
env->analyzer_priv = priv; env->analyzer_priv = priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment