Commit 6aff67c8 authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by David S. Miller

bpf: fix check_map_func_compatibility logic

The commit 35578d79 ("bpf: Implement function bpf_perf_event_read() that get the selected hardware PMU conuter")
introduced clever way to check bpf_helper<->map_type compatibility.
Later on commit a43eec30 ("bpf: introduce bpf_perf_event_output() helper") adjusted
the logic and inadvertently broke it.
Get rid of the clever bool compare and go back to two-way check
from map and from helper perspective.

Fixes: a43eec30 ("bpf: introduce bpf_perf_event_output() helper")
Reported-by: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92117d84
...@@ -239,16 +239,6 @@ static const char * const reg_type_str[] = { ...@@ -239,16 +239,6 @@ static const char * const reg_type_str[] = {
[CONST_IMM] = "imm", [CONST_IMM] = "imm",
}; };
static const struct {
int map_type;
int func_id;
} func_limit[] = {
{BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call},
{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read},
{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_output},
{BPF_MAP_TYPE_STACK_TRACE, BPF_FUNC_get_stackid},
};
static void print_verifier_state(struct verifier_env *env) static void print_verifier_state(struct verifier_env *env)
{ {
enum bpf_reg_type t; enum bpf_reg_type t;
...@@ -921,27 +911,52 @@ static int check_func_arg(struct verifier_env *env, u32 regno, ...@@ -921,27 +911,52 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
static int check_map_func_compatibility(struct bpf_map *map, int func_id) static int check_map_func_compatibility(struct bpf_map *map, int func_id)
{ {
bool bool_map, bool_func;
int i;
if (!map) if (!map)
return 0; return 0;
for (i = 0; i < ARRAY_SIZE(func_limit); i++) { /* We need a two way check, first is from map perspective ... */
bool_map = (map->map_type == func_limit[i].map_type); switch (map->map_type) {
bool_func = (func_id == func_limit[i].func_id); case BPF_MAP_TYPE_PROG_ARRAY:
/* only when map & func pair match it can continue. if (func_id != BPF_FUNC_tail_call)
* don't allow any other map type to be passed into goto error;
* the special func; break;
*/ case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
if (bool_func && bool_map != bool_func) { if (func_id != BPF_FUNC_perf_event_read &&
verbose("cannot pass map_type %d into func %d\n", func_id != BPF_FUNC_perf_event_output)
map->map_type, func_id); goto error;
return -EINVAL; break;
} case BPF_MAP_TYPE_STACK_TRACE:
if (func_id != BPF_FUNC_get_stackid)
goto error;
break;
default:
break;
}
/* ... and second from the function itself. */
switch (func_id) {
case BPF_FUNC_tail_call:
if (map->map_type != BPF_MAP_TYPE_PROG_ARRAY)
goto error;
break;
case BPF_FUNC_perf_event_read:
case BPF_FUNC_perf_event_output:
if (map->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
goto error;
break;
case BPF_FUNC_get_stackid:
if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
goto error;
break;
default:
break;
} }
return 0; return 0;
error:
verbose("cannot pass map_type %d into func %d\n",
map->map_type, func_id);
return -EINVAL;
} }
static int check_call(struct verifier_env *env, int func_id) static int check_call(struct verifier_env *env, int func_id)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment