Patch "bpf: fix check_map_func_compatibility logic" has been added to the 4.5-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
bpf: fix check_map_func_compatibility logic
to the 4.5-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
bpf-fix-check_map_func_compatibility-logic.patch
and it can be found in the queue-4.5 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Mon May 16 11:20:33 PDT 2016
From: Alexei Starovoitov <[email protected]>
Date: Wed, 27 Apr 2016 18:56:21 -0700
Subject: bpf: fix check_map_func_compatibility logic
From: Alexei Starovoitov <[email protected]>
[ Upstream commit 6aff67c85c9e5a4bc99e5211c1bac547936626ca ]
The commit 35578d798400 ("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 a43eec304259 ("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.
--- kernel/bpf/verifier.c | 53 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 21 deletions(-)
kernel/bpf/verifier.c +32 -21
@@ -239,15 +239,6 @@ static const char * const reg_type_str[] [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}, -}; -static void print_verifier_state (struct verifier_env *env) {enum bpf_reg_type t;
@@ -898,24 +889,44 @@ static int check_func_arg(struct verifiestatic int check_map_func_compatibility (struct bpf_map *map,int func_id) { -bool bool_map, bool_func; -int i; -if (!map)return 0 ; -for (i =0 ; i <ARRAY_SIZE (func_limit); i++) { - bool_map = (map->map_type == func_limit[i].map_type); - bool_func = (func_id == func_limit[i].func_id); -/* only when map & func pair match it can continue. -* don't allow any other map type to be passed into -* the special func; -*/ -if (bool_func && bool_map != bool_func) -return -EINVAL ; +/* We need a two way check, first is from map perspective ... */ +switch (map->map_type) { +case BPF_MAP_TYPE_PROG_ARRAY : +if (func_id != BPF_FUNC_tail_call) + goto error; +break ; +case BPF_MAP_TYPE_PERF_EVENT_ARRAY : +if (func_id != BPF_FUNC_perf_event_read && + func_id != BPF_FUNC_perf_event_output) + 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 ; +default : +break ; }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)
Patches currently in stable-queue which might be from [email protected] are
queue-4.5/samples-bpf-fix-trace_output-example.patch queue-4.5/bpf-fix-refcnt-overflow.patch queue-4.5/bpf-verifier-reject-invalid-ld_abs-bpf_dw-instruction.patch queue-4.5/bpf-fix-check_map_func_compatibility-logic.patch