@@ -1092,7 +1092,7 @@ static int check_subprogs(struct bpf_verifier_env *env)
10921092 */
10931093 subprog [env -> subprog_cnt ].start = insn_cnt ;
10941094
1095- if (env -> log .level > 1 )
1095+ if (env -> log .level & BPF_LOG_LEVEL2 )
10961096 for (i = 0 ; i < env -> subprog_cnt ; i ++ )
10971097 verbose (env , "func#%d @%d\n" , i , subprog [i ].start );
10981098
@@ -1139,6 +1139,7 @@ static int mark_reg_read(struct bpf_verifier_env *env,
11391139 struct bpf_reg_state * parent )
11401140{
11411141 bool writes = parent == state -> parent ; /* Observe write marks */
1142+ int cnt = 0 ;
11421143
11431144 while (parent ) {
11441145 /* if read wasn't screened by an earlier write ... */
@@ -1155,7 +1156,11 @@ static int mark_reg_read(struct bpf_verifier_env *env,
11551156 state = parent ;
11561157 parent = state -> parent ;
11571158 writes = true;
1159+ cnt ++ ;
11581160 }
1161+
1162+ if (env -> longest_mark_read_walk < cnt )
1163+ env -> longest_mark_read_walk = cnt ;
11591164 return 0 ;
11601165}
11611166
@@ -1455,7 +1460,7 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno,
14551460 * need to try adding each of min_value and max_value to off
14561461 * to make sure our theoretical access will be safe.
14571462 */
1458- if (env -> log .level )
1463+ if (env -> log .level & BPF_LOG_LEVEL )
14591464 print_verifier_state (env , state );
14601465
14611466 /* The minimum value is only important with signed
@@ -2938,7 +2943,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
29382943 /* and go analyze first insn of the callee */
29392944 * insn_idx = target_insn ;
29402945
2941- if (env -> log .level ) {
2946+ if (env -> log .level & BPF_LOG_LEVEL ) {
29422947 verbose (env , "caller:\n" );
29432948 print_verifier_state (env , caller );
29442949 verbose (env , "callee:\n" );
@@ -2978,7 +2983,7 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
29782983 return err ;
29792984
29802985 * insn_idx = callee -> callsite + 1 ;
2981- if (env -> log .level ) {
2986+ if (env -> log .level & BPF_LOG_LEVEL ) {
29822987 verbose (env , "returning from callee:\n" );
29832988 print_verifier_state (env , callee );
29842989 verbose (env , "to caller at %d:\n" , * insn_idx );
@@ -5001,7 +5006,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
50015006 insn -> dst_reg );
50025007 return - EACCES ;
50035008 }
5004- if (env -> log .level )
5009+ if (env -> log .level & BPF_LOG_LEVEL )
50055010 print_verifier_state (env , this_branch -> frame [this_branch -> curframe ]);
50065011 return 0 ;
50075012}
@@ -6181,6 +6186,9 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
61816186 states_cnt ++ ;
61826187 }
61836188
6189+ if (env -> max_states_per_insn < states_cnt )
6190+ env -> max_states_per_insn = states_cnt ;
6191+
61846192 if (!env -> allow_ptr_leaks && states_cnt > BPF_COMPLEXITY_LIMIT_STATES )
61856193 return 0 ;
61866194
@@ -6194,6 +6202,8 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
61946202 new_sl = kzalloc (sizeof (struct bpf_verifier_state_list ), GFP_KERNEL );
61956203 if (!new_sl )
61966204 return - ENOMEM ;
6205+ env -> total_states ++ ;
6206+ env -> peak_states ++ ;
61976207
61986208 /* add new state to the head of linked list */
61996209 new = & new_sl -> state ;
@@ -6278,8 +6288,7 @@ static int do_check(struct bpf_verifier_env *env)
62786288 struct bpf_verifier_state * state ;
62796289 struct bpf_insn * insns = env -> prog -> insnsi ;
62806290 struct bpf_reg_state * regs ;
6281- int insn_cnt = env -> prog -> len , i ;
6282- int insn_processed = 0 ;
6291+ int insn_cnt = env -> prog -> len ;
62836292 bool do_print_state = false;
62846293
62856294 env -> prev_linfo = NULL ;
@@ -6314,10 +6323,10 @@ static int do_check(struct bpf_verifier_env *env)
63146323 insn = & insns [env -> insn_idx ];
63156324 class = BPF_CLASS (insn -> code );
63166325
6317- if (++ insn_processed > BPF_COMPLEXITY_LIMIT_INSNS ) {
6326+ if (++ env -> insn_processed > BPF_COMPLEXITY_LIMIT_INSNS ) {
63186327 verbose (env ,
63196328 "BPF program is too large. Processed %d insn\n" ,
6320- insn_processed );
6329+ env -> insn_processed );
63216330 return - E2BIG ;
63226331 }
63236332
@@ -6326,7 +6335,7 @@ static int do_check(struct bpf_verifier_env *env)
63266335 return err ;
63276336 if (err == 1 ) {
63286337 /* found equivalent state, can prune the search */
6329- if (env -> log .level ) {
6338+ if (env -> log .level & BPF_LOG_LEVEL ) {
63306339 if (do_print_state )
63316340 verbose (env , "\nfrom %d to %d%s: safe\n" ,
63326341 env -> prev_insn_idx , env -> insn_idx ,
@@ -6344,8 +6353,9 @@ static int do_check(struct bpf_verifier_env *env)
63446353 if (need_resched ())
63456354 cond_resched ();
63466355
6347- if (env -> log .level > 1 || (env -> log .level && do_print_state )) {
6348- if (env -> log .level > 1 )
6356+ if (env -> log .level & BPF_LOG_LEVEL2 ||
6357+ (env -> log .level & BPF_LOG_LEVEL && do_print_state )) {
6358+ if (env -> log .level & BPF_LOG_LEVEL2 )
63496359 verbose (env , "%d:" , env -> insn_idx );
63506360 else
63516361 verbose (env , "\nfrom %d to %d%s:" ,
@@ -6356,7 +6366,7 @@ static int do_check(struct bpf_verifier_env *env)
63566366 do_print_state = false;
63576367 }
63586368
6359- if (env -> log .level ) {
6369+ if (env -> log .level & BPF_LOG_LEVEL ) {
63606370 const struct bpf_insn_cbs cbs = {
63616371 .cb_print = verbose ,
63626372 .private_data = env ,
@@ -6621,16 +6631,6 @@ static int do_check(struct bpf_verifier_env *env)
66216631 env -> insn_idx ++ ;
66226632 }
66236633
6624- verbose (env , "processed %d insns (limit %d), stack depth " ,
6625- insn_processed , BPF_COMPLEXITY_LIMIT_INSNS );
6626- for (i = 0 ; i < env -> subprog_cnt ; i ++ ) {
6627- u32 depth = env -> subprog_info [i ].stack_depth ;
6628-
6629- verbose (env , "%d" , depth );
6630- if (i + 1 < env -> subprog_cnt )
6631- verbose (env , "+" );
6632- }
6633- verbose (env , "\n" );
66346634 env -> prog -> aux -> stack_depth = env -> subprog_info [0 ].stack_depth ;
66356635 return 0 ;
66366636}
@@ -7854,9 +7854,34 @@ static void free_states(struct bpf_verifier_env *env)
78547854 kfree (env -> explored_states );
78557855}
78567856
7857+ static void print_verification_stats (struct bpf_verifier_env * env )
7858+ {
7859+ int i ;
7860+
7861+ if (env -> log .level & BPF_LOG_STATS ) {
7862+ verbose (env , "verification time %lld usec\n" ,
7863+ div_u64 (env -> verification_time , 1000 ));
7864+ verbose (env , "stack depth " );
7865+ for (i = 0 ; i < env -> subprog_cnt ; i ++ ) {
7866+ u32 depth = env -> subprog_info [i ].stack_depth ;
7867+
7868+ verbose (env , "%d" , depth );
7869+ if (i + 1 < env -> subprog_cnt )
7870+ verbose (env , "+" );
7871+ }
7872+ verbose (env , "\n" );
7873+ }
7874+ verbose (env , "processed %d insns (limit %d) max_states_per_insn %d "
7875+ "total_states %d peak_states %d mark_read %d\n" ,
7876+ env -> insn_processed , BPF_COMPLEXITY_LIMIT_INSNS ,
7877+ env -> max_states_per_insn , env -> total_states ,
7878+ env -> peak_states , env -> longest_mark_read_walk );
7879+ }
7880+
78577881int bpf_check (struct bpf_prog * * prog , union bpf_attr * attr ,
78587882 union bpf_attr __user * uattr )
78597883{
7884+ u64 start_time = ktime_get_ns ();
78607885 struct bpf_verifier_env * env ;
78617886 struct bpf_verifier_log * log ;
78627887 int i , len , ret = - EINVAL ;
@@ -7899,7 +7924,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
78997924 ret = - EINVAL ;
79007925 /* log attributes have to be sane */
79017926 if (log -> len_total < 128 || log -> len_total > UINT_MAX >> 8 ||
7902- !log -> level || !log -> ubuf )
7927+ !log -> level || !log -> ubuf || log -> level & ~ BPF_LOG_MASK )
79037928 goto err_unlock ;
79047929 }
79057930
@@ -7980,6 +8005,9 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
79808005 if (ret == 0 )
79818006 ret = fixup_call_args (env );
79828007
8008+ env -> verification_time = ktime_get_ns () - start_time ;
8009+ print_verification_stats (env );
8010+
79838011 if (log -> level && bpf_verifier_log_full (log ))
79848012 ret = - ENOSPC ;
79858013 if (log -> level && !log -> ubuf ) {
0 commit comments