@@ -355,12 +355,14 @@ static char slot_type_char[] = {
355355static void print_liveness (struct bpf_verifier_env * env ,
356356 enum bpf_reg_liveness live )
357357{
358- if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN ))
358+ if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN | REG_LIVE_DONE ))
359359 verbose (env , "_" );
360360 if (live & REG_LIVE_READ )
361361 verbose (env , "r" );
362362 if (live & REG_LIVE_WRITTEN )
363363 verbose (env , "w" );
364+ if (live & REG_LIVE_DONE )
365+ verbose (env , "D" );
364366}
365367
366368static struct bpf_func_state * func (struct bpf_verifier_env * env ,
@@ -1126,6 +1128,12 @@ static int mark_reg_read(struct bpf_verifier_env *env,
11261128 /* if read wasn't screened by an earlier write ... */
11271129 if (writes && state -> live & REG_LIVE_WRITTEN )
11281130 break ;
1131+ if (parent -> live & REG_LIVE_DONE ) {
1132+ verbose (env , "verifier BUG type %s var_off %lld off %d\n" ,
1133+ reg_type_str [parent -> type ],
1134+ parent -> var_off .value , parent -> off );
1135+ return - EFAULT ;
1136+ }
11291137 /* ... then we depend on parent's value */
11301138 parent -> live |= REG_LIVE_READ ;
11311139 state = parent ;
@@ -5695,6 +5703,102 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_id_pair *idmap)
56955703 return false;
56965704}
56975705
5706+ static void clean_func_state (struct bpf_verifier_env * env ,
5707+ struct bpf_func_state * st )
5708+ {
5709+ enum bpf_reg_liveness live ;
5710+ int i , j ;
5711+
5712+ for (i = 0 ; i < BPF_REG_FP ; i ++ ) {
5713+ live = st -> regs [i ].live ;
5714+ /* liveness must not touch this register anymore */
5715+ st -> regs [i ].live |= REG_LIVE_DONE ;
5716+ if (!(live & REG_LIVE_READ ))
5717+ /* since the register is unused, clear its state
5718+ * to make further comparison simpler
5719+ */
5720+ __mark_reg_not_init (& st -> regs [i ]);
5721+ }
5722+
5723+ for (i = 0 ; i < st -> allocated_stack / BPF_REG_SIZE ; i ++ ) {
5724+ live = st -> stack [i ].spilled_ptr .live ;
5725+ /* liveness must not touch this stack slot anymore */
5726+ st -> stack [i ].spilled_ptr .live |= REG_LIVE_DONE ;
5727+ if (!(live & REG_LIVE_READ )) {
5728+ __mark_reg_not_init (& st -> stack [i ].spilled_ptr );
5729+ for (j = 0 ; j < BPF_REG_SIZE ; j ++ )
5730+ st -> stack [i ].slot_type [j ] = STACK_INVALID ;
5731+ }
5732+ }
5733+ }
5734+
5735+ static void clean_verifier_state (struct bpf_verifier_env * env ,
5736+ struct bpf_verifier_state * st )
5737+ {
5738+ int i ;
5739+
5740+ if (st -> frame [0 ]-> regs [0 ].live & REG_LIVE_DONE )
5741+ /* all regs in this state in all frames were already marked */
5742+ return ;
5743+
5744+ for (i = 0 ; i <= st -> curframe ; i ++ )
5745+ clean_func_state (env , st -> frame [i ]);
5746+ }
5747+
5748+ /* the parentage chains form a tree.
5749+ * the verifier states are added to state lists at given insn and
5750+ * pushed into state stack for future exploration.
5751+ * when the verifier reaches bpf_exit insn some of the verifer states
5752+ * stored in the state lists have their final liveness state already,
5753+ * but a lot of states will get revised from liveness point of view when
5754+ * the verifier explores other branches.
5755+ * Example:
5756+ * 1: r0 = 1
5757+ * 2: if r1 == 100 goto pc+1
5758+ * 3: r0 = 2
5759+ * 4: exit
5760+ * when the verifier reaches exit insn the register r0 in the state list of
5761+ * insn 2 will be seen as !REG_LIVE_READ. Then the verifier pops the other_branch
5762+ * of insn 2 and goes exploring further. At the insn 4 it will walk the
5763+ * parentage chain from insn 4 into insn 2 and will mark r0 as REG_LIVE_READ.
5764+ *
5765+ * Since the verifier pushes the branch states as it sees them while exploring
5766+ * the program the condition of walking the branch instruction for the second
5767+ * time means that all states below this branch were already explored and
5768+ * their final liveness markes are already propagated.
5769+ * Hence when the verifier completes the search of state list in is_state_visited()
5770+ * we can call this clean_live_states() function to mark all liveness states
5771+ * as REG_LIVE_DONE to indicate that 'parent' pointers of 'struct bpf_reg_state'
5772+ * will not be used.
5773+ * This function also clears the registers and stack for states that !READ
5774+ * to simplify state merging.
5775+ *
5776+ * Important note here that walking the same branch instruction in the callee
5777+ * doesn't meant that the states are DONE. The verifier has to compare
5778+ * the callsites
5779+ */
5780+ static void clean_live_states (struct bpf_verifier_env * env , int insn ,
5781+ struct bpf_verifier_state * cur )
5782+ {
5783+ struct bpf_verifier_state_list * sl ;
5784+ int i ;
5785+
5786+ sl = env -> explored_states [insn ];
5787+ if (!sl )
5788+ return ;
5789+
5790+ while (sl != STATE_LIST_MARK ) {
5791+ if (sl -> state .curframe != cur -> curframe )
5792+ goto next ;
5793+ for (i = 0 ; i <= cur -> curframe ; i ++ )
5794+ if (sl -> state .frame [i ]-> callsite != cur -> frame [i ]-> callsite )
5795+ goto next ;
5796+ clean_verifier_state (env , & sl -> state );
5797+ next :
5798+ sl = sl -> next ;
5799+ }
5800+ }
5801+
56985802/* Returns true if (rold safe implies rcur safe) */
56995803static bool regsafe (struct bpf_verifier_env * env , struct bpf_reg_state * rold ,
57005804 struct bpf_reg_state * rcur , struct bpf_id_pair * idmap )
@@ -6010,6 +6114,8 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
60106114 */
60116115 return 0 ;
60126116
6117+ clean_live_states (env , insn_idx , cur );
6118+
60136119 while (sl != STATE_LIST_MARK ) {
60146120 if (states_equal (env , & sl -> state , cur )) {
60156121 /* reached equivalent register/stack state,
0 commit comments