bpf: allow map helpers access to map values directly
Subsystems (4)
PATCH v5 1/2 bpf: allow map helpers access to map values directly
Helpers that expect ARG_PTR_TO_MAP_KEY and ARG_PTR_TO_MAP_VALUE can only access stack and packet memory. Allow these helpers to directly access map values by passing registers of type PTR_TO_MAP_VALUE.
This change removes the need for an extra copy to the stack when using a map value to perform a second map lookup, as in the following:
struct bpf_map_def SEC("maps") infobyreq = {
.type = BPF_MAP_TYPE_HASHMAP,
.key_size = sizeof(struct request *),
.value_size = sizeof(struct info_t),
.max_entries = 1024,
};
struct bpf_map_def SEC("maps") counts = {
.type = BPF_MAP_TYPE_HASHMAP,
.key_size = sizeof(struct info_t),
.value_size = sizeof(u64),
.max_entries = 1024,
};SEC("kprobe/blk_account_io_start")
int bpf_blk_account_io_start(struct pt_regs *ctx)
{
struct info_t *info = bpf_map_lookup_elem(&infobyreq, &ctx->di);
u64 *count = bpf_map_lookup_elem(&counts, info);
(*count)++;
}--- kernel/bpf/verifier.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-)
kernel/bpf/verifier.c +7 -17
@@ -1914,7 +1914,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,if (arg_type ==ARG_PTR_TO_MAP_KEY || arg_type ==ARG_PTR_TO_MAP_VALUE ) { expected_type =PTR_TO_STACK ; -if (!type_is_pkt_pointer (type) && +if (!type_is_pkt_pointer (type) && type !=PTR_TO_MAP_VALUE && type != expected_type) goto err_type; } else if (arg_type == ARG_CONST_SIZE ||
@@ -1966,14 +1966,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,verbose (env,"invalid map_ptr to access map->key\n" );return -EACCES ; } -if (type_is_pkt_pointer (type)) - err =check_packet_access (env, regno, reg->off, - meta->map_ptr->key_size, - false); -else - err =check_stack_boundary (env, regno, - meta->map_ptr->key_size, - false,NULL ); + err =check_helper_mem_access (env, regno, + meta->map_ptr->key_size, false, +NULL ); }else if (arg_type ==ARG_PTR_TO_MAP_VALUE ) {/* bpf_map_xxx(..., map_ptr, ..., value) call: * check [value, value + map->value_size) validity
@@ -1983,14 +1978,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,verbose (env,"invalid map_ptr to access map->value\n" );return -EACCES ; } -if (type_is_pkt_pointer (type)) - err =check_packet_access (env, regno, reg->off, - meta->map_ptr->value_size, - false); -else - err =check_stack_boundary (env, regno, - meta->map_ptr->value_size, - false,NULL ); + err =check_helper_mem_access (env, regno, + meta->map_ptr->value_size, false, +NULL ); }else if (arg_type_is_mem_size (arg_type)) {bool zero_size_allowed = (arg_type ==ARG_CONST_SIZE_OR_ZERO );
Signature · 1 line
2.7.4