Remove ARG_PTR_TO_MAP_VALUE_OR_NULL and use flag to mark that the argument may be null. Signed-off-by: Hao Luo <haoluo@xxxxxxxxxx> --- include/linux/bpf.h | 6 +++++- kernel/bpf/bpf_inode_storage.c | 5 ++++- kernel/bpf/bpf_task_storage.c | 5 ++++- kernel/bpf/verifier.c | 11 +++++------ net/core/bpf_sk_storage.c | 15 ++++++++++++--- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 287d819e73f8..d8de8f00e40d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -297,6 +297,9 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0, extern const struct bpf_map_ops bpf_map_offload_ops; +/* argument may be null or zero */ +#define ARG_FLAG_MAYBE_NULL 1 + /* function argument constraints */ struct bpf_arg_type { enum { @@ -309,7 +312,6 @@ struct bpf_arg_type { ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */ ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */ ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */ - ARG_PTR_TO_MAP_VALUE_OR_NULL, /* pointer to stack used as map value or NULL */ /* the following constraints used to prototype bpf_memcmp() and other * functions that access data on eBPF program stack @@ -345,6 +347,8 @@ struct bpf_arg_type { ARG_PTR_TO_TIMER, /* pointer to bpf_timer */ __BPF_ARG_TYPE_MAX, } type; + + u8 flag; }; /* type of values returned from helper functions */ diff --git a/kernel/bpf/bpf_inode_storage.c b/kernel/bpf/bpf_inode_storage.c index 091352613225..acb566a3b37f 100644 --- a/kernel/bpf/bpf_inode_storage.c +++ b/kernel/bpf/bpf_inode_storage.c @@ -265,7 +265,10 @@ const struct bpf_func_proto bpf_inode_storage_get_proto = { .arg1 = { .type = ARG_CONST_MAP_PTR, } .arg2 = { .type = ARG_PTR_TO_BTF_ID, } .arg2_btf_id = &bpf_inode_storage_btf_ids[0], - .arg3 = { .type = ARG_PTR_TO_MAP_VALUE_OR_NULL, } + .arg3 = { + .type = ARG_PTR_TO_MAP_VALUE, + .flag = ARG_FLAG_MAYBE_NULL, + } .arg4_type = { .type = ARG_ANYTHING, } }; diff --git a/kernel/bpf/bpf_task_storage.c b/kernel/bpf/bpf_task_storage.c index 04bb681edc78..bdc0925c2fd3 100644 --- a/kernel/bpf/bpf_task_storage.c +++ b/kernel/bpf/bpf_task_storage.c @@ -324,7 +324,10 @@ const struct bpf_func_proto bpf_task_storage_get_proto = { .arg1 = { .type = ARG_CONST_MAP_PTR }, .arg2 = { .type = ARG_PTR_TO_BTF_ID }, .arg2_btf_id = &btf_task_struct_ids[0], - .arg3 = { .type = ARG_PTR_TO_MAP_VALUE_OR_NULL }, + .arg3 = { + .type = ARG_PTR_TO_MAP_VALUE, + .flag = ARG_FLAG_MAYBE_NULL, + }, .arg4 = { .type = ARG_ANYTHING }, }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1f2aaa2214d9..f55967f92d22 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -480,7 +480,7 @@ static bool arg_type_may_be_refcounted(struct bpf_arg_type arg) static bool arg_type_may_be_null(struct bpf_arg_type arg) { - return arg.type == ARG_PTR_TO_MAP_VALUE_OR_NULL || + return arg.flag & ARG_FLAG_MAYBE_NULL || arg.type == ARG_PTR_TO_MEM_OR_NULL || arg.type == ARG_PTR_TO_CTX_OR_NULL || arg.type == ARG_PTR_TO_SOCKET_OR_NULL || @@ -5089,7 +5089,6 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, [ARG_PTR_TO_MAP_VALUE] = &map_key_value_types, [ARG_PTR_TO_UNINIT_MAP_VALUE] = &map_key_value_types, - [ARG_PTR_TO_MAP_VALUE_OR_NULL] = &map_key_value_types, [ARG_CONST_SIZE] = &scalar_types, [ARG_CONST_SIZE_OR_ZERO] = &scalar_types, [ARG_CONST_ALLOC_SIZE_OR_ZERO] = &scalar_types, @@ -5209,8 +5208,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg_num, } if (arg.type == ARG_PTR_TO_MAP_VALUE || - arg.type == ARG_PTR_TO_UNINIT_MAP_VALUE || - arg.type == ARG_PTR_TO_MAP_VALUE_OR_NULL) { + arg.type == ARG_PTR_TO_UNINIT_MAP_VALUE) { err = resolve_map_arg_type(env, meta, &arg); if (err) return err; @@ -5286,9 +5284,10 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg_num, meta->map_ptr->key_size, false, NULL); } else if (arg.type == ARG_PTR_TO_MAP_VALUE || - (arg.type == ARG_PTR_TO_MAP_VALUE_OR_NULL && - !register_is_null(reg)) || arg.type == ARG_PTR_TO_UNINIT_MAP_VALUE) { + if ((arg.flag & ARG_FLAG_MAYBE_NULL) && register_is_null(reg)) + return err; + /* bpf_map_xxx(..., map_ptr, ..., value) call: * check [value, value + map->value_size) validity */ diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c index 81f8529c0169..22fdbe3d68e3 100644 --- a/net/core/bpf_sk_storage.c +++ b/net/core/bpf_sk_storage.c @@ -357,7 +357,10 @@ const struct bpf_func_proto bpf_sk_storage_get_proto = { .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL, .arg1 = { .type = ARG_CONST_MAP_PTR }, .arg2 = { .type = ARG_PTR_TO_BTF_ID_SOCK_COMMON }, - .arg3 = { .type = ARG_PTR_TO_MAP_VALUE_OR_NULL }, + .arg3 = { + .type = ARG_PTR_TO_MAP_VALUE, + .flag = ARG_FLAG_MAYBE_NULL, + }, .arg4 = { .type = ARG_ANYTHING }, }; @@ -367,7 +370,10 @@ const struct bpf_func_proto bpf_sk_storage_get_cg_sock_proto = { .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL, .arg1 = { .type = ARG_CONST_MAP_PTR }, .arg2 = { .type = ARG_PTR_TO_CTX }, /* context is 'struct sock' */ - .arg3 = { .type = ARG_PTR_TO_MAP_VALUE_OR_NULL }, + .arg3 = { + .type = ARG_PTR_TO_MAP_VALUE, + .flag = ARG_FLAG_MAYBE_NULL, + }, .arg4 = { .type = ARG_ANYTHING }, }; @@ -438,7 +444,10 @@ const struct bpf_func_proto bpf_sk_storage_get_tracing_proto = { .arg1 = { .type = ARG_CONST_MAP_PTR }, .arg2 = { .type = ARG_PTR_TO_BTF_ID }, .arg2_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON], - .arg3 = { .type = ARG_PTR_TO_MAP_VALUE_OR_NULL }, + .arg3 = { + .type = ARG_PTR_TO_MAP_VALUE, + .flag = ARG_FLAG_MAYBE_NULL, + }, .arg4 = { .type = ARG_ANYTHING }, .allowed = bpf_sk_storage_tracing_allowed, }; -- 2.34.0.rc0.344.g81b53c2807-goog