Skip to content

Commit 3c48073

Browse files
haoluo1022Alexei Starovoitov
authored andcommitted
bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL
We have introduced a new type to make bpf_ret composable, by reserving high bits to represent flags. One of the flag is PTR_MAYBE_NULL, which indicates a pointer may be NULL. When applying this flag to ret_types, it means the returned value could be a NULL pointer. This patch switches the qualified arg_types to use this flag. The ret_types changed in this patch include: 1. RET_PTR_TO_MAP_VALUE_OR_NULL 2. RET_PTR_TO_SOCKET_OR_NULL 3. RET_PTR_TO_TCP_SOCK_OR_NULL 4. RET_PTR_TO_SOCK_COMMON_OR_NULL 5. RET_PTR_TO_ALLOC_MEM_OR_NULL 6. RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL 7. RET_PTR_TO_BTF_ID_OR_NULL This patch doesn't eliminate the use of these names, instead it makes them aliases to 'RET_PTR_TO_XXX | PTR_MAYBE_NULL'. Signed-off-by: Hao Luo <haoluo@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20211217003152.48334-4-haoluo@google.com
1 parent 48946bd commit 3c48073

File tree

3 files changed

+39
-34
lines changed

3 files changed

+39
-34
lines changed

include/linux/bpf.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,17 +382,22 @@ enum bpf_return_type {
382382
RET_INTEGER, /* function returns integer */
383383
RET_VOID, /* function doesn't return anything */
384384
RET_PTR_TO_MAP_VALUE, /* returns a pointer to map elem value */
385-
RET_PTR_TO_MAP_VALUE_OR_NULL, /* returns a pointer to map elem value or NULL */
386-
RET_PTR_TO_SOCKET_OR_NULL, /* returns a pointer to a socket or NULL */
387-
RET_PTR_TO_TCP_SOCK_OR_NULL, /* returns a pointer to a tcp_sock or NULL */
388-
RET_PTR_TO_SOCK_COMMON_OR_NULL, /* returns a pointer to a sock_common or NULL */
389-
RET_PTR_TO_ALLOC_MEM_OR_NULL, /* returns a pointer to dynamically allocated memory or NULL */
390-
RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */
391-
RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */
385+
RET_PTR_TO_SOCKET, /* returns a pointer to a socket */
386+
RET_PTR_TO_TCP_SOCK, /* returns a pointer to a tcp_sock */
387+
RET_PTR_TO_SOCK_COMMON, /* returns a pointer to a sock_common */
388+
RET_PTR_TO_ALLOC_MEM, /* returns a pointer to dynamically allocated memory */
392389
RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */
393390
RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */
394391
__BPF_RET_TYPE_MAX,
395392

393+
/* Extended ret_types. */
394+
RET_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MAP_VALUE,
395+
RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET,
396+
RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK,
397+
RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON,
398+
RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_ALLOC_MEM,
399+
RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID,
400+
396401
/* This must be the last entry. Its purpose is to ensure the enum is
397402
* wide enough to hold the higher bits reserved for bpf_type_flag.
398403
*/

kernel/bpf/helpers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ BPF_CALL_2(bpf_per_cpu_ptr, const void *, ptr, u32, cpu)
682682
const struct bpf_func_proto bpf_per_cpu_ptr_proto = {
683683
.func = bpf_per_cpu_ptr,
684684
.gpl_only = false,
685-
.ret_type = RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL,
685+
.ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL,
686686
.arg1_type = ARG_PTR_TO_PERCPU_BTF_ID,
687687
.arg2_type = ARG_ANYTHING,
688688
};

kernel/bpf/verifier.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6473,6 +6473,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
64736473
int *insn_idx_p)
64746474
{
64756475
const struct bpf_func_proto *fn = NULL;
6476+
enum bpf_return_type ret_type;
64766477
struct bpf_reg_state *regs;
64776478
struct bpf_call_arg_meta meta;
64786479
int insn_idx = *insn_idx_p;
@@ -6612,13 +6613,13 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
66126613
regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
66136614

66146615
/* update return register (already marked as written above) */
6615-
if (fn->ret_type == RET_INTEGER) {
6616+
ret_type = fn->ret_type;
6617+
if (ret_type == RET_INTEGER) {
66166618
/* sets type to SCALAR_VALUE */
66176619
mark_reg_unknown(env, regs, BPF_REG_0);
6618-
} else if (fn->ret_type == RET_VOID) {
6620+
} else if (ret_type == RET_VOID) {
66196621
regs[BPF_REG_0].type = NOT_INIT;
6620-
} else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL ||
6621-
fn->ret_type == RET_PTR_TO_MAP_VALUE) {
6622+
} else if (base_type(ret_type) == RET_PTR_TO_MAP_VALUE) {
66226623
/* There is no offset yet applied, variable or fixed */
66236624
mark_reg_known_zero(env, regs, BPF_REG_0);
66246625
/* remember map_ptr, so that check_map_access()
@@ -6632,28 +6633,27 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
66326633
}
66336634
regs[BPF_REG_0].map_ptr = meta.map_ptr;
66346635
regs[BPF_REG_0].map_uid = meta.map_uid;
6635-
if (fn->ret_type == RET_PTR_TO_MAP_VALUE) {
6636+
if (type_may_be_null(ret_type)) {
6637+
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
6638+
} else {
66366639
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
66376640
if (map_value_has_spin_lock(meta.map_ptr))
66386641
regs[BPF_REG_0].id = ++env->id_gen;
6639-
} else {
6640-
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
66416642
}
6642-
} else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) {
6643+
} else if (base_type(ret_type) == RET_PTR_TO_SOCKET) {
66436644
mark_reg_known_zero(env, regs, BPF_REG_0);
66446645
regs[BPF_REG_0].type = PTR_TO_SOCKET_OR_NULL;
6645-
} else if (fn->ret_type == RET_PTR_TO_SOCK_COMMON_OR_NULL) {
6646+
} else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) {
66466647
mark_reg_known_zero(env, regs, BPF_REG_0);
66476648
regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON_OR_NULL;
6648-
} else if (fn->ret_type == RET_PTR_TO_TCP_SOCK_OR_NULL) {
6649+
} else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) {
66496650
mark_reg_known_zero(env, regs, BPF_REG_0);
66506651
regs[BPF_REG_0].type = PTR_TO_TCP_SOCK_OR_NULL;
6651-
} else if (fn->ret_type == RET_PTR_TO_ALLOC_MEM_OR_NULL) {
6652+
} else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) {
66526653
mark_reg_known_zero(env, regs, BPF_REG_0);
66536654
regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL;
66546655
regs[BPF_REG_0].mem_size = meta.mem_size;
6655-
} else if (fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL ||
6656-
fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID) {
6656+
} else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) {
66576657
const struct btf_type *t;
66586658

66596659
mark_reg_known_zero(env, regs, BPF_REG_0);
@@ -6672,28 +6672,28 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
66726672
return -EINVAL;
66736673
}
66746674
regs[BPF_REG_0].type =
6675-
fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ?
6676-
PTR_TO_MEM : PTR_TO_MEM_OR_NULL;
6675+
(ret_type & PTR_MAYBE_NULL) ?
6676+
PTR_TO_MEM_OR_NULL : PTR_TO_MEM;
66776677
regs[BPF_REG_0].mem_size = tsize;
66786678
} else {
66796679
regs[BPF_REG_0].type =
6680-
fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ?
6681-
PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL;
6680+
(ret_type & PTR_MAYBE_NULL) ?
6681+
PTR_TO_BTF_ID_OR_NULL : PTR_TO_BTF_ID;
66826682
regs[BPF_REG_0].btf = meta.ret_btf;
66836683
regs[BPF_REG_0].btf_id = meta.ret_btf_id;
66846684
}
6685-
} else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL ||
6686-
fn->ret_type == RET_PTR_TO_BTF_ID) {
6685+
} else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) {
66876686
int ret_btf_id;
66886687

66896688
mark_reg_known_zero(env, regs, BPF_REG_0);
6690-
regs[BPF_REG_0].type = fn->ret_type == RET_PTR_TO_BTF_ID ?
6691-
PTR_TO_BTF_ID :
6692-
PTR_TO_BTF_ID_OR_NULL;
6689+
regs[BPF_REG_0].type = (ret_type & PTR_MAYBE_NULL) ?
6690+
PTR_TO_BTF_ID_OR_NULL :
6691+
PTR_TO_BTF_ID;
66936692
ret_btf_id = *fn->ret_btf_id;
66946693
if (ret_btf_id == 0) {
6695-
verbose(env, "invalid return type %d of func %s#%d\n",
6696-
fn->ret_type, func_id_name(func_id), func_id);
6694+
verbose(env, "invalid return type %u of func %s#%d\n",
6695+
base_type(ret_type), func_id_name(func_id),
6696+
func_id);
66976697
return -EINVAL;
66986698
}
66996699
/* current BPF helper definitions are only coming from
@@ -6702,8 +6702,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
67026702
regs[BPF_REG_0].btf = btf_vmlinux;
67036703
regs[BPF_REG_0].btf_id = ret_btf_id;
67046704
} else {
6705-
verbose(env, "unknown return type %d of func %s#%d\n",
6706-
fn->ret_type, func_id_name(func_id), func_id);
6705+
verbose(env, "unknown return type %u of func %s#%d\n",
6706+
base_type(ret_type), func_id_name(func_id), func_id);
67076707
return -EINVAL;
67086708
}
67096709

0 commit comments

Comments
 (0)