Skip to content

Commit c1f3276

Browse files
liuhangbinkernel-patches-bot
authored andcommitted
bpf: add a new bpf argument type ARG_CONST_MAP_PTR_OR_NULL
Add a new bpf argument type ARG_CONST_MAP_PTR_OR_NULL which could be used when we want to allow NULL pointer for map parameter. The bpf helper need to take care and check if the map is NULL when use this type. Add a new variable map_ptr_cnt in struct bpf_call_arg_meta to disable key/value argument check if there are multiple map pointers in the same function. Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
1 parent c345f9f commit c1f3276

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ enum bpf_arg_type {
295295
ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
296296
ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */
297297
ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */
298+
ARG_CONST_MAP_PTR_OR_NULL, /* const argument used as pointer to bpf_map or NULL */
298299
__BPF_ARG_TYPE_MAX,
299300
};
300301

kernel/bpf/verifier.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
189192
static 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

253257
struct 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

Comments
 (0)