bpf: remove global variables
Move three global variables protected by bpf_verifier_lock into 'struct bpf_verifier_env' to allow parallel verification. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
3b8802446d
commit
7df737e991
|
@ -295,6 +295,11 @@ struct bpf_verifier_env {
|
||||||
const struct bpf_line_info *prev_linfo;
|
const struct bpf_line_info *prev_linfo;
|
||||||
struct bpf_verifier_log log;
|
struct bpf_verifier_log log;
|
||||||
struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1];
|
struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1];
|
||||||
|
struct {
|
||||||
|
int *insn_state;
|
||||||
|
int *insn_stack;
|
||||||
|
int cur_stack;
|
||||||
|
} cfg;
|
||||||
u32 subprog_cnt;
|
u32 subprog_cnt;
|
||||||
/* number of instructions analyzed by the verifier */
|
/* number of instructions analyzed by the verifier */
|
||||||
u32 insn_processed;
|
u32 insn_processed;
|
||||||
|
|
|
@ -5369,10 +5369,6 @@ enum {
|
||||||
|
|
||||||
#define STATE_LIST_MARK ((struct bpf_verifier_state_list *) -1L)
|
#define STATE_LIST_MARK ((struct bpf_verifier_state_list *) -1L)
|
||||||
|
|
||||||
static int *insn_stack; /* stack of insns to process */
|
|
||||||
static int cur_stack; /* current stack index */
|
|
||||||
static int *insn_state;
|
|
||||||
|
|
||||||
/* t, w, e - match pseudo-code above:
|
/* t, w, e - match pseudo-code above:
|
||||||
* t - index of current instruction
|
* t - index of current instruction
|
||||||
* w - next instruction
|
* w - next instruction
|
||||||
|
@ -5380,6 +5376,9 @@ static int *insn_state;
|
||||||
*/
|
*/
|
||||||
static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
|
static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
|
||||||
{
|
{
|
||||||
|
int *insn_stack = env->cfg.insn_stack;
|
||||||
|
int *insn_state = env->cfg.insn_state;
|
||||||
|
|
||||||
if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH))
|
if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -5400,9 +5399,9 @@ static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
|
||||||
/* tree-edge */
|
/* tree-edge */
|
||||||
insn_state[t] = DISCOVERED | e;
|
insn_state[t] = DISCOVERED | e;
|
||||||
insn_state[w] = DISCOVERED;
|
insn_state[w] = DISCOVERED;
|
||||||
if (cur_stack >= env->prog->len)
|
if (env->cfg.cur_stack >= env->prog->len)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
insn_stack[cur_stack++] = w;
|
insn_stack[env->cfg.cur_stack++] = w;
|
||||||
return 1;
|
return 1;
|
||||||
} else if ((insn_state[w] & 0xF0) == DISCOVERED) {
|
} else if ((insn_state[w] & 0xF0) == DISCOVERED) {
|
||||||
verbose_linfo(env, t, "%d: ", t);
|
verbose_linfo(env, t, "%d: ", t);
|
||||||
|
@ -5426,14 +5425,15 @@ static int check_cfg(struct bpf_verifier_env *env)
|
||||||
{
|
{
|
||||||
struct bpf_insn *insns = env->prog->insnsi;
|
struct bpf_insn *insns = env->prog->insnsi;
|
||||||
int insn_cnt = env->prog->len;
|
int insn_cnt = env->prog->len;
|
||||||
|
int *insn_stack, *insn_state;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i, t;
|
int i, t;
|
||||||
|
|
||||||
insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
|
insn_state = env->cfg.insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
|
||||||
if (!insn_state)
|
if (!insn_state)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
|
insn_stack = env->cfg.insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
|
||||||
if (!insn_stack) {
|
if (!insn_stack) {
|
||||||
kvfree(insn_state);
|
kvfree(insn_state);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -5441,12 +5441,12 @@ static int check_cfg(struct bpf_verifier_env *env)
|
||||||
|
|
||||||
insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */
|
insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */
|
||||||
insn_stack[0] = 0; /* 0 is the first instruction */
|
insn_stack[0] = 0; /* 0 is the first instruction */
|
||||||
cur_stack = 1;
|
env->cfg.cur_stack = 1;
|
||||||
|
|
||||||
peek_stack:
|
peek_stack:
|
||||||
if (cur_stack == 0)
|
if (env->cfg.cur_stack == 0)
|
||||||
goto check_state;
|
goto check_state;
|
||||||
t = insn_stack[cur_stack - 1];
|
t = insn_stack[env->cfg.cur_stack - 1];
|
||||||
|
|
||||||
if (BPF_CLASS(insns[t].code) == BPF_JMP ||
|
if (BPF_CLASS(insns[t].code) == BPF_JMP ||
|
||||||
BPF_CLASS(insns[t].code) == BPF_JMP32) {
|
BPF_CLASS(insns[t].code) == BPF_JMP32) {
|
||||||
|
@ -5515,7 +5515,7 @@ peek_stack:
|
||||||
|
|
||||||
mark_explored:
|
mark_explored:
|
||||||
insn_state[t] = EXPLORED;
|
insn_state[t] = EXPLORED;
|
||||||
if (cur_stack-- <= 0) {
|
if (env->cfg.cur_stack-- <= 0) {
|
||||||
verbose(env, "pop stack internal bug\n");
|
verbose(env, "pop stack internal bug\n");
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
@ -5535,6 +5535,7 @@ check_state:
|
||||||
err_free:
|
err_free:
|
||||||
kvfree(insn_state);
|
kvfree(insn_state);
|
||||||
kvfree(insn_stack);
|
kvfree(insn_stack);
|
||||||
|
env->cfg.insn_state = env->cfg.insn_stack = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue