@@ -249,6 +249,11 @@ static bool type_is_pkt_pointer(enum bpf_reg_type type)
249249 type == PTR_TO_PACKET_META ;
250250}
251251
252+ static bool reg_type_may_be_null (enum bpf_reg_type type )
253+ {
254+ return type == PTR_TO_MAP_VALUE_OR_NULL ;
255+ }
256+
252257/* string representation of 'enum bpf_reg_type' */
253258static const char * const reg_type_str [] = {
254259 [NOT_INIT ] = "?" ,
@@ -3599,12 +3604,10 @@ static void reg_combine_min_max(struct bpf_reg_state *true_src,
35993604 }
36003605}
36013606
3602- static void mark_map_reg (struct bpf_reg_state * regs , u32 regno , u32 id ,
3603- bool is_null )
3607+ static void mark_ptr_or_null_reg (struct bpf_reg_state * reg , u32 id ,
3608+ bool is_null )
36043609{
3605- struct bpf_reg_state * reg = & regs [regno ];
3606-
3607- if (reg -> type == PTR_TO_MAP_VALUE_OR_NULL && reg -> id == id ) {
3610+ if (reg_type_may_be_null (reg -> type ) && reg -> id == id ) {
36083611 /* Old offset (both fixed and variable parts) should
36093612 * have been known-zero, because we don't allow pointer
36103613 * arithmetic on pointers that might be NULL.
@@ -3617,11 +3620,13 @@ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
36173620 }
36183621 if (is_null ) {
36193622 reg -> type = SCALAR_VALUE ;
3620- } else if (reg -> map_ptr -> inner_map_meta ) {
3621- reg -> type = CONST_PTR_TO_MAP ;
3622- reg -> map_ptr = reg -> map_ptr -> inner_map_meta ;
3623- } else {
3624- reg -> type = PTR_TO_MAP_VALUE ;
3623+ } else if (reg -> type == PTR_TO_MAP_VALUE_OR_NULL ) {
3624+ if (reg -> map_ptr -> inner_map_meta ) {
3625+ reg -> type = CONST_PTR_TO_MAP ;
3626+ reg -> map_ptr = reg -> map_ptr -> inner_map_meta ;
3627+ } else {
3628+ reg -> type = PTR_TO_MAP_VALUE ;
3629+ }
36253630 }
36263631 /* We don't need id from this point onwards anymore, thus we
36273632 * should better reset it, so that state pruning has chances
@@ -3634,23 +3639,23 @@ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
36343639/* The logic is similar to find_good_pkt_pointers(), both could eventually
36353640 * be folded together at some point.
36363641 */
3637- static void mark_map_regs (struct bpf_verifier_state * vstate , u32 regno ,
3638- bool is_null )
3642+ static void mark_ptr_or_null_regs (struct bpf_verifier_state * vstate , u32 regno ,
3643+ bool is_null )
36393644{
36403645 struct bpf_func_state * state = vstate -> frame [vstate -> curframe ];
36413646 struct bpf_reg_state * reg , * regs = state -> regs ;
36423647 u32 id = regs [regno ].id ;
36433648 int i , j ;
36443649
36453650 for (i = 0 ; i < MAX_BPF_REG ; i ++ )
3646- mark_map_reg ( regs , i , id , is_null );
3651+ mark_ptr_or_null_reg ( & regs [ i ] , id , is_null );
36473652
36483653 for (j = 0 ; j <= vstate -> curframe ; j ++ ) {
36493654 state = vstate -> frame [j ];
36503655 bpf_for_each_spilled_reg (i , state , reg ) {
36513656 if (!reg )
36523657 continue ;
3653- mark_map_reg ( & state -> stack [ i ]. spilled_ptr , 0 , id , is_null );
3658+ mark_ptr_or_null_reg ( reg , id , is_null );
36543659 }
36553660 }
36563661}
@@ -3852,12 +3857,14 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
38523857 /* detect if R == 0 where R is returned from bpf_map_lookup_elem() */
38533858 if (BPF_SRC (insn -> code ) == BPF_K &&
38543859 insn -> imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE ) &&
3855- dst_reg -> type == PTR_TO_MAP_VALUE_OR_NULL ) {
3856- /* Mark all identical map registers in each branch as either
3860+ reg_type_may_be_null ( dst_reg -> type ) ) {
3861+ /* Mark all identical registers in each branch as either
38573862 * safe or unknown depending R == 0 or R != 0 conditional.
38583863 */
3859- mark_map_regs (this_branch , insn -> dst_reg , opcode == BPF_JNE );
3860- mark_map_regs (other_branch , insn -> dst_reg , opcode == BPF_JEQ );
3864+ mark_ptr_or_null_regs (this_branch , insn -> dst_reg ,
3865+ opcode == BPF_JNE );
3866+ mark_ptr_or_null_regs (other_branch , insn -> dst_reg ,
3867+ opcode == BPF_JEQ );
38613868 } else if (!try_match_pkt_pointers (insn , dst_reg , & regs [insn -> src_reg ],
38623869 this_branch , other_branch ) &&
38633870 is_pointer_value (env , insn -> dst_reg )) {
0 commit comments