OSDN Git Service

bpf: remove global variables
authorAlexei Starovoitov <ast@kernel.org>
Fri, 19 Apr 2019 14:44:54 +0000 (07:44 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 22 Apr 2019 23:50:43 +0000 (01:50 +0200)
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>
include/linux/bpf_verifier.h
kernel/bpf/verifier.c

index b3ab61f..1305ccb 100644 (file)
@@ -295,6 +295,11 @@ struct bpf_verifier_env {
        const struct bpf_line_info *prev_linfo;
        struct bpf_verifier_log log;
        struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1];
+       struct {
+               int *insn_state;
+               int *insn_stack;
+               int cur_stack;
+       } cfg;
        u32 subprog_cnt;
        /* number of instructions analyzed by the verifier */
        u32 insn_processed;
index db301e9..5f0eb5b 100644 (file)
@@ -5369,10 +5369,6 @@ enum {
 
 #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 - index of current 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)
 {
+       int *insn_stack = env->cfg.insn_stack;
+       int *insn_state = env->cfg.insn_state;
+
        if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH))
                return 0;
 
@@ -5400,9 +5399,9 @@ static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
                /* tree-edge */
                insn_state[t] = DISCOVERED | e;
                insn_state[w] = DISCOVERED;
-               if (cur_stack >= env->prog->len)
+               if (env->cfg.cur_stack >= env->prog->len)
                        return -E2BIG;
-               insn_stack[cur_stack++] = w;
+               insn_stack[env->cfg.cur_stack++] = w;
                return 1;
        } else if ((insn_state[w] & 0xF0) == DISCOVERED) {
                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;
        int insn_cnt = env->prog->len;
+       int *insn_stack, *insn_state;
        int ret = 0;
        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)
                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) {
                kvfree(insn_state);
                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_stack[0] = 0; /* 0 is the first instruction */
-       cur_stack = 1;
+       env->cfg.cur_stack = 1;
 
 peek_stack:
-       if (cur_stack == 0)
+       if (env->cfg.cur_stack == 0)
                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 ||
            BPF_CLASS(insns[t].code) == BPF_JMP32) {
@@ -5515,7 +5515,7 @@ peek_stack:
 
 mark_explored:
        insn_state[t] = EXPLORED;
-       if (cur_stack-- <= 0) {
+       if (env->cfg.cur_stack-- <= 0) {
                verbose(env, "pop stack internal bug\n");
                ret = -EFAULT;
                goto err_free;
@@ -5535,6 +5535,7 @@ check_state:
 err_free:
        kvfree(insn_state);
        kvfree(insn_stack);
+       env->cfg.insn_state = env->cfg.insn_stack = NULL;
        return ret;
 }