aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-04-22 19:50:44 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2019-04-22 19:51:49 -0400
commitf79b464fd6b56b6256de43bc4c7d5968c0e52968 (patch)
treeb87c6007123c872988d8939f8206a8ec8907bb39
parent3b8802446d27522cd6d32178ba975cc492611f31 (diff)
parent45a73c17bfb92c3ceebedc80a750ef2c2931c26b (diff)
Merge branch 'bpf-verifier-lock'
Alexei Starovoitov says: ==================== Allow the bpf verifier to run in parallel for root. ==================== Acked-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--include/linux/bpf_verifier.h5
-rw-r--r--kernel/bpf/verifier.c33
2 files changed, 23 insertions, 15 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index b3ab61fe1932..1305ccbd8fe6 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -295,6 +295,11 @@ struct bpf_verifier_env {
295 const struct bpf_line_info *prev_linfo; 295 const struct bpf_line_info *prev_linfo;
296 struct bpf_verifier_log log; 296 struct bpf_verifier_log log;
297 struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1]; 297 struct bpf_subprog_info subprog_info[BPF_MAX_SUBPROGS + 1];
298 struct {
299 int *insn_state;
300 int *insn_stack;
301 int cur_stack;
302 } cfg;
298 u32 subprog_cnt; 303 u32 subprog_cnt;
299 /* number of instructions analyzed by the verifier */ 304 /* number of instructions analyzed by the verifier */
300 u32 insn_processed; 305 u32 insn_processed;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index db301e9b5295..423f242a5efb 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5369,10 +5369,6 @@ enum {
5369 5369
5370#define STATE_LIST_MARK ((struct bpf_verifier_state_list *) -1L) 5370#define STATE_LIST_MARK ((struct bpf_verifier_state_list *) -1L)
5371 5371
5372static int *insn_stack; /* stack of insns to process */
5373static int cur_stack; /* current stack index */
5374static int *insn_state;
5375
5376/* t, w, e - match pseudo-code above: 5372/* t, w, e - match pseudo-code above:
5377 * t - index of current instruction 5373 * t - index of current instruction
5378 * w - next instruction 5374 * w - next instruction
@@ -5380,6 +5376,9 @@ static int *insn_state;
5380 */ 5376 */
5381static int push_insn(int t, int w, int e, struct bpf_verifier_env *env) 5377static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
5382{ 5378{
5379 int *insn_stack = env->cfg.insn_stack;
5380 int *insn_state = env->cfg.insn_state;
5381
5383 if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH)) 5382 if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH))
5384 return 0; 5383 return 0;
5385 5384
@@ -5400,9 +5399,9 @@ static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
5400 /* tree-edge */ 5399 /* tree-edge */
5401 insn_state[t] = DISCOVERED | e; 5400 insn_state[t] = DISCOVERED | e;
5402 insn_state[w] = DISCOVERED; 5401 insn_state[w] = DISCOVERED;
5403 if (cur_stack >= env->prog->len) 5402 if (env->cfg.cur_stack >= env->prog->len)
5404 return -E2BIG; 5403 return -E2BIG;
5405 insn_stack[cur_stack++] = w; 5404 insn_stack[env->cfg.cur_stack++] = w;
5406 return 1; 5405 return 1;
5407 } else if ((insn_state[w] & 0xF0) == DISCOVERED) { 5406 } else if ((insn_state[w] & 0xF0) == DISCOVERED) {
5408 verbose_linfo(env, t, "%d: ", t); 5407 verbose_linfo(env, t, "%d: ", t);
@@ -5426,14 +5425,15 @@ static int check_cfg(struct bpf_verifier_env *env)
5426{ 5425{
5427 struct bpf_insn *insns = env->prog->insnsi; 5426 struct bpf_insn *insns = env->prog->insnsi;
5428 int insn_cnt = env->prog->len; 5427 int insn_cnt = env->prog->len;
5428 int *insn_stack, *insn_state;
5429 int ret = 0; 5429 int ret = 0;
5430 int i, t; 5430 int i, t;
5431 5431
5432 insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5432 insn_state = env->cfg.insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
5433 if (!insn_state) 5433 if (!insn_state)
5434 return -ENOMEM; 5434 return -ENOMEM;
5435 5435
5436 insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL); 5436 insn_stack = env->cfg.insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
5437 if (!insn_stack) { 5437 if (!insn_stack) {
5438 kvfree(insn_state); 5438 kvfree(insn_state);
5439 return -ENOMEM; 5439 return -ENOMEM;
@@ -5441,12 +5441,12 @@ static int check_cfg(struct bpf_verifier_env *env)
5441 5441
5442 insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */ 5442 insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */
5443 insn_stack[0] = 0; /* 0 is the first instruction */ 5443 insn_stack[0] = 0; /* 0 is the first instruction */
5444 cur_stack = 1; 5444 env->cfg.cur_stack = 1;
5445 5445
5446peek_stack: 5446peek_stack:
5447 if (cur_stack == 0) 5447 if (env->cfg.cur_stack == 0)
5448 goto check_state; 5448 goto check_state;
5449 t = insn_stack[cur_stack - 1]; 5449 t = insn_stack[env->cfg.cur_stack - 1];
5450 5450
5451 if (BPF_CLASS(insns[t].code) == BPF_JMP || 5451 if (BPF_CLASS(insns[t].code) == BPF_JMP ||
5452 BPF_CLASS(insns[t].code) == BPF_JMP32) { 5452 BPF_CLASS(insns[t].code) == BPF_JMP32) {
@@ -5515,7 +5515,7 @@ peek_stack:
5515 5515
5516mark_explored: 5516mark_explored:
5517 insn_state[t] = EXPLORED; 5517 insn_state[t] = EXPLORED;
5518 if (cur_stack-- <= 0) { 5518 if (env->cfg.cur_stack-- <= 0) {
5519 verbose(env, "pop stack internal bug\n"); 5519 verbose(env, "pop stack internal bug\n");
5520 ret = -EFAULT; 5520 ret = -EFAULT;
5521 goto err_free; 5521 goto err_free;
@@ -5535,6 +5535,7 @@ check_state:
5535err_free: 5535err_free:
5536 kvfree(insn_state); 5536 kvfree(insn_state);
5537 kvfree(insn_stack); 5537 kvfree(insn_stack);
5538 env->cfg.insn_state = env->cfg.insn_stack = NULL;
5538 return ret; 5539 return ret;
5539} 5540}
5540 5541
@@ -8131,9 +8132,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
8131 env->insn_aux_data[i].orig_idx = i; 8132 env->insn_aux_data[i].orig_idx = i;
8132 env->prog = *prog; 8133 env->prog = *prog;
8133 env->ops = bpf_verifier_ops[env->prog->type]; 8134 env->ops = bpf_verifier_ops[env->prog->type];
8135 is_priv = capable(CAP_SYS_ADMIN);
8134 8136
8135 /* grab the mutex to protect few globals used by verifier */ 8137 /* grab the mutex to protect few globals used by verifier */
8136 mutex_lock(&bpf_verifier_lock); 8138 if (!is_priv)
8139 mutex_lock(&bpf_verifier_lock);
8137 8140
8138 if (attr->log_level || attr->log_buf || attr->log_size) { 8141 if (attr->log_level || attr->log_buf || attr->log_size) {
8139 /* user requested verbose verifier output 8142 /* user requested verbose verifier output
@@ -8156,7 +8159,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
8156 if (attr->prog_flags & BPF_F_ANY_ALIGNMENT) 8159 if (attr->prog_flags & BPF_F_ANY_ALIGNMENT)
8157 env->strict_alignment = false; 8160 env->strict_alignment = false;
8158 8161
8159 is_priv = capable(CAP_SYS_ADMIN);
8160 env->allow_ptr_leaks = is_priv; 8162 env->allow_ptr_leaks = is_priv;
8161 8163
8162 ret = replace_map_fd_with_map_ptr(env); 8164 ret = replace_map_fd_with_map_ptr(env);
@@ -8269,7 +8271,8 @@ err_release_maps:
8269 release_maps(env); 8271 release_maps(env);
8270 *prog = env->prog; 8272 *prog = env->prog;
8271err_unlock: 8273err_unlock:
8272 mutex_unlock(&bpf_verifier_lock); 8274 if (!is_priv)
8275 mutex_unlock(&bpf_verifier_lock);
8273 vfree(env->insn_aux_data); 8276 vfree(env->insn_aux_data);
8274err_free_env: 8277err_free_env:
8275 kfree(env); 8278 kfree(env);