@@ -186,6 +186,9 @@ struct bpf_verifier_stack_elem {
186186 POISON_POINTER_DELTA))
187187#define BPF_MAP_PTR (X ) ((struct bpf_map *)((X) & ~BPF_MAP_PTR_UNPRIV))
188188
189+ static int check_map_func_compatibility (struct bpf_verifier_env * env ,
190+ struct bpf_map * map , int func_id );
191+
189192static bool bpf_map_ptr_poisoned (const struct bpf_insn_aux_data * aux )
190193{
191194 return BPF_MAP_PTR (aux -> map_ptr_state ) == BPF_MAP_PTR_POISON ;
@@ -248,6 +251,7 @@ struct bpf_call_arg_meta {
248251 u32 btf_id ;
249252 struct btf * ret_btf ;
250253 u32 ret_btf_id ;
254+ int map_ptr_cnt ;
251255};
252256
253257struct btf * btf_vmlinux ;
@@ -451,7 +455,8 @@ static bool arg_type_may_be_null(enum bpf_arg_type type)
451455 type == ARG_PTR_TO_MEM_OR_NULL ||
452456 type == ARG_PTR_TO_CTX_OR_NULL ||
453457 type == ARG_PTR_TO_SOCKET_OR_NULL ||
454- type == ARG_PTR_TO_ALLOC_MEM_OR_NULL ;
458+ type == ARG_PTR_TO_ALLOC_MEM_OR_NULL ||
459+ type == ARG_CONST_MAP_PTR_OR_NULL ;
455460}
456461
457462/* Determine whether the function releases some resources allocated by another
@@ -4512,6 +4517,7 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
45124517 [ARG_CONST_SIZE_OR_ZERO ] = & scalar_types ,
45134518 [ARG_CONST_ALLOC_SIZE_OR_ZERO ] = & scalar_types ,
45144519 [ARG_CONST_MAP_PTR ] = & const_map_ptr_types ,
4520+ [ARG_CONST_MAP_PTR_OR_NULL ] = & const_map_ptr_types ,
45154521 [ARG_PTR_TO_CTX ] = & context_types ,
45164522 [ARG_PTR_TO_CTX_OR_NULL ] = & context_types ,
45174523 [ARG_PTR_TO_SOCK_COMMON ] = & sock_types ,
@@ -4657,9 +4663,22 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
46574663 meta -> ref_obj_id = reg -> ref_obj_id ;
46584664 }
46594665
4660- if (arg_type == ARG_CONST_MAP_PTR ) {
4661- /* bpf_map_xxx(map_ptr) call: remember that map_ptr */
4662- meta -> map_ptr = reg -> map_ptr ;
4666+ if (arg_type == ARG_CONST_MAP_PTR ||
4667+ arg_type == ARG_CONST_MAP_PTR_OR_NULL ) {
4668+ if (!register_is_null (reg )) {
4669+ err = check_map_func_compatibility (env , reg -> map_ptr , meta -> func_id );
4670+ if (err )
4671+ return err ;
4672+ meta -> map_ptr = reg -> map_ptr ;
4673+ }
4674+ /* With multiple map pointers in the same function signature,
4675+ * any future checks using the cached map_ptr become ambiguous
4676+ * (which of the maps would it be referring to?), so unset
4677+ * map_ptr to trigger the error conditions in the checks that
4678+ * use it.
4679+ */
4680+ if (++ meta -> map_ptr_cnt > 1 )
4681+ meta -> map_ptr = NULL ;
46634682 } else if (arg_type == ARG_PTR_TO_MAP_KEY ) {
46644683 /* bpf_map_xxx(..., map_ptr, ..., key) call:
46654684 * check that [key, key + map->key_size) are within
@@ -5717,10 +5736,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
57175736
57185737 do_refine_retval_range (regs , fn -> ret_type , func_id , & meta );
57195738
5720- err = check_map_func_compatibility (env , meta .map_ptr , func_id );
5721- if (err )
5722- return err ;
5723-
57245739 if ((func_id == BPF_FUNC_get_stack ||
57255740 func_id == BPF_FUNC_get_task_stack ) &&
57265741 !env -> prog -> has_callchain_buf ) {
0 commit comments