Skip to content

Commit 16d1e00

Browse files
joannekoongAlexei Starovoitov
authored andcommitted
bpf: Add MEM_UNINIT as a bpf_type_flag
Instead of having uninitialized versions of arguments as separate bpf_arg_types (eg ARG_PTR_TO_UNINIT_MEM as the uninitialized version of ARG_PTR_TO_MEM), we can instead use MEM_UNINIT as a bpf_type_flag modifier to denote that the argument is uninitialized. Doing so cleans up some of the logic in the verifier. We no longer need to do two checks against an argument type (eg "if (base_type(arg_type) == ARG_PTR_TO_MEM || base_type(arg_type) == ARG_PTR_TO_UNINIT_MEM)"), since uninitialized and initialized versions of the same argument type will now share the same base type. In the near future, MEM_UNINIT will be used by dynptr helper functions as well. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Acked-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: David Vernet <void@manifault.com> Link: https://lore.kernel.org/r/20220509224257.3222614-2-joannelkoong@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 0d2d264 commit 16d1e00

File tree

3 files changed

+20
-30
lines changed

3 files changed

+20
-30
lines changed

include/linux/bpf.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,10 @@ enum bpf_type_flag {
390390
*/
391391
PTR_UNTRUSTED = BIT(6 + BPF_BASE_TYPE_BITS),
392392

393-
__BPF_TYPE_LAST_FLAG = PTR_UNTRUSTED,
393+
MEM_UNINIT = BIT(7 + BPF_BASE_TYPE_BITS),
394+
395+
__BPF_TYPE_FLAG_MAX,
396+
__BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1,
394397
};
395398

396399
/* Max number of base types. */
@@ -409,16 +412,11 @@ enum bpf_arg_type {
409412
ARG_CONST_MAP_PTR, /* const argument used as pointer to bpf_map */
410413
ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
411414
ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */
412-
ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */
413415

414-
/* the following constraints used to prototype bpf_memcmp() and other
415-
* functions that access data on eBPF program stack
416+
/* Used to prototype bpf_memcmp() and other functions that access data
417+
* on eBPF program stack
416418
*/
417419
ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */
418-
ARG_PTR_TO_UNINIT_MEM, /* pointer to memory does not need to be initialized,
419-
* helper function must fill all bytes or clear
420-
* them in error case.
421-
*/
422420

423421
ARG_CONST_SIZE, /* number of bytes accessed from memory */
424422
ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */
@@ -450,6 +448,10 @@ enum bpf_arg_type {
450448
ARG_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_ALLOC_MEM,
451449
ARG_PTR_TO_STACK_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_STACK,
452450
ARG_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_BTF_ID,
451+
/* pointer to memory does not need to be initialized, helper function must fill
452+
* all bytes or clear them in error case.
453+
*/
454+
ARG_PTR_TO_UNINIT_MEM = MEM_UNINIT | ARG_PTR_TO_MEM,
453455

454456
/* This must be the last entry. Its purpose is to ensure the enum is
455457
* wide enough to hold the higher bits reserved for bpf_type_flag.

kernel/bpf/helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const struct bpf_func_proto bpf_map_pop_elem_proto = {
103103
.gpl_only = false,
104104
.ret_type = RET_INTEGER,
105105
.arg1_type = ARG_CONST_MAP_PTR,
106-
.arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
106+
.arg2_type = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT,
107107
};
108108

109109
BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
@@ -116,7 +116,7 @@ const struct bpf_func_proto bpf_map_peek_elem_proto = {
116116
.gpl_only = false,
117117
.ret_type = RET_INTEGER,
118118
.arg1_type = ARG_CONST_MAP_PTR,
119-
.arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
119+
.arg2_type = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT,
120120
};
121121

122122
BPF_CALL_3(bpf_map_lookup_percpu_elem, struct bpf_map *, map, void *, key, u32, cpu)

kernel/bpf/verifier.c

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5377,12 +5377,6 @@ static int process_kptr_func(struct bpf_verifier_env *env, int regno,
53775377
return 0;
53785378
}
53795379

5380-
static bool arg_type_is_mem_ptr(enum bpf_arg_type type)
5381-
{
5382-
return base_type(type) == ARG_PTR_TO_MEM ||
5383-
base_type(type) == ARG_PTR_TO_UNINIT_MEM;
5384-
}
5385-
53865380
static bool arg_type_is_mem_size(enum bpf_arg_type type)
53875381
{
53885382
return type == ARG_CONST_SIZE ||
@@ -5522,7 +5516,6 @@ static const struct bpf_reg_types kptr_types = { .types = { PTR_TO_MAP_VALUE } }
55225516
static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
55235517
[ARG_PTR_TO_MAP_KEY] = &map_key_value_types,
55245518
[ARG_PTR_TO_MAP_VALUE] = &map_key_value_types,
5525-
[ARG_PTR_TO_UNINIT_MAP_VALUE] = &map_key_value_types,
55265519
[ARG_CONST_SIZE] = &scalar_types,
55275520
[ARG_CONST_SIZE_OR_ZERO] = &scalar_types,
55285521
[ARG_CONST_ALLOC_SIZE_OR_ZERO] = &scalar_types,
@@ -5536,7 +5529,6 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
55365529
[ARG_PTR_TO_BTF_ID] = &btf_ptr_types,
55375530
[ARG_PTR_TO_SPIN_LOCK] = &spin_lock_types,
55385531
[ARG_PTR_TO_MEM] = &mem_types,
5539-
[ARG_PTR_TO_UNINIT_MEM] = &mem_types,
55405532
[ARG_PTR_TO_ALLOC_MEM] = &alloc_mem_types,
55415533
[ARG_PTR_TO_INT] = &int_ptr_types,
55425534
[ARG_PTR_TO_LONG] = &int_ptr_types,
@@ -5710,8 +5702,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
57105702
return -EACCES;
57115703
}
57125704

5713-
if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE ||
5714-
base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) {
5705+
if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE) {
57155706
err = resolve_map_arg_type(env, meta, &arg_type);
57165707
if (err)
57175708
return err;
@@ -5797,8 +5788,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
57975788
err = check_helper_mem_access(env, regno,
57985789
meta->map_ptr->key_size, false,
57995790
NULL);
5800-
} else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE ||
5801-
base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) {
5791+
} else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE) {
58025792
if (type_may_be_null(arg_type) && register_is_null(reg))
58035793
return 0;
58045794

@@ -5810,7 +5800,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
58105800
verbose(env, "invalid map_ptr to access map->value\n");
58115801
return -EACCES;
58125802
}
5813-
meta->raw_mode = (arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE);
5803+
meta->raw_mode = arg_type & MEM_UNINIT;
58145804
err = check_helper_mem_access(env, regno,
58155805
meta->map_ptr->value_size, false,
58165806
meta);
@@ -5837,11 +5827,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
58375827
return -EACCES;
58385828
} else if (arg_type == ARG_PTR_TO_FUNC) {
58395829
meta->subprogno = reg->subprogno;
5840-
} else if (arg_type_is_mem_ptr(arg_type)) {
5830+
} else if (base_type(arg_type) == ARG_PTR_TO_MEM) {
58415831
/* The access to this pointer is only checked when we hit the
58425832
* next is_mem_size argument below.
58435833
*/
5844-
meta->raw_mode = (arg_type == ARG_PTR_TO_UNINIT_MEM);
5834+
meta->raw_mode = arg_type & MEM_UNINIT;
58455835
} else if (arg_type_is_mem_size(arg_type)) {
58465836
bool zero_size_allowed = (arg_type == ARG_CONST_SIZE_OR_ZERO);
58475837

@@ -6194,10 +6184,8 @@ static bool check_raw_mode_ok(const struct bpf_func_proto *fn)
61946184
static bool check_args_pair_invalid(enum bpf_arg_type arg_curr,
61956185
enum bpf_arg_type arg_next)
61966186
{
6197-
return (arg_type_is_mem_ptr(arg_curr) &&
6198-
!arg_type_is_mem_size(arg_next)) ||
6199-
(!arg_type_is_mem_ptr(arg_curr) &&
6200-
arg_type_is_mem_size(arg_next));
6187+
return (base_type(arg_curr) == ARG_PTR_TO_MEM) !=
6188+
arg_type_is_mem_size(arg_next);
62016189
}
62026190

62036191
static bool check_arg_pair_ok(const struct bpf_func_proto *fn)
@@ -6208,7 +6196,7 @@ static bool check_arg_pair_ok(const struct bpf_func_proto *fn)
62086196
* helper function specification.
62096197
*/
62106198
if (arg_type_is_mem_size(fn->arg1_type) ||
6211-
arg_type_is_mem_ptr(fn->arg5_type) ||
6199+
base_type(fn->arg5_type) == ARG_PTR_TO_MEM ||
62126200
check_args_pair_invalid(fn->arg1_type, fn->arg2_type) ||
62136201
check_args_pair_invalid(fn->arg2_type, fn->arg3_type) ||
62146202
check_args_pair_invalid(fn->arg3_type, fn->arg4_type) ||

0 commit comments

Comments
 (0)