| From foo@baz Sun Jun 17 12:07:34 CEST 2018 |
| From: Mark Rutland <mark.rutland@arm.com> |
| Date: Thu, 3 May 2018 17:04:59 +0100 |
| Subject: bpf: fix possible spectre-v1 in find_and_alloc_map() |
| |
| From: Mark Rutland <mark.rutland@arm.com> |
| |
| [ Upstream commit 9ef09e35e521bf0df5325cc9cffa726a8f5f3c1b ] |
| |
| It's possible for userspace to control attr->map_type. Sanitize it when |
| using it as an array index to prevent an out-of-bounds value being used |
| under speculation. |
| |
| Found by smatch. |
| |
| Signed-off-by: Mark Rutland <mark.rutland@arm.com> |
| Cc: Alexei Starovoitov <ast@kernel.org> |
| Cc: Dan Carpenter <dan.carpenter@oracle.com> |
| Cc: Daniel Borkmann <daniel@iogearbox.net> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: netdev@vger.kernel.org |
| Acked-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| kernel/bpf/syscall.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| --- a/kernel/bpf/syscall.c |
| +++ b/kernel/bpf/syscall.c |
| @@ -26,6 +26,7 @@ |
| #include <linux/cred.h> |
| #include <linux/timekeeping.h> |
| #include <linux/ctype.h> |
| +#include <linux/nospec.h> |
| |
| #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \ |
| (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ |
| @@ -102,12 +103,14 @@ const struct bpf_map_ops bpf_map_offload |
| static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) |
| { |
| const struct bpf_map_ops *ops; |
| + u32 type = attr->map_type; |
| struct bpf_map *map; |
| int err; |
| |
| - if (attr->map_type >= ARRAY_SIZE(bpf_map_types)) |
| + if (type >= ARRAY_SIZE(bpf_map_types)) |
| return ERR_PTR(-EINVAL); |
| - ops = bpf_map_types[attr->map_type]; |
| + type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types)); |
| + ops = bpf_map_types[type]; |
| if (!ops) |
| return ERR_PTR(-EINVAL); |
| |
| @@ -122,7 +125,7 @@ static struct bpf_map *find_and_alloc_ma |
| if (IS_ERR(map)) |
| return map; |
| map->ops = ops; |
| - map->map_type = attr->map_type; |
| + map->map_type = type; |
| return map; |
| } |
| |