| From foo@baz Wed Apr 17 20:59:12 CEST 2019 |
| From: Balbir Singh <sblbir@amzn.com> |
| Date: Wed, 3 Apr 2019 18:39:08 +0000 |
| Subject: bpf: restrict map value pointer arithmetic for unprivileged |
| To: <gregkh@linuxfoundation.org> |
| Cc: <stable@kernel.org>, <daniel@iogearbox.net>, <jannh@google.com>, <sblbir@amazon.com>, Alexei Starovoitov <ast@kernel.org> |
| Message-ID: <20190403183917.13749-9-sblbir@amzn.com> |
| |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| |
| commit 0d6303db7970e6f56ae700fa07e11eb510cda125 upstream. |
| |
| Restrict map value pointer arithmetic for unprivileged users in that |
| arithmetic itself must not go out of bounds as opposed to the actual |
| access later on. Therefore after each adjust_ptr_min_max_vals() with a |
| map value pointer as a destination it will simulate a check_map_access() |
| of 1 byte on the destination and once that fails the program is rejected |
| for unprivileged program loads. We use this later on for masking any |
| pointer arithmetic with the remainder of the map value space. The |
| likelihood of breaking any existing real-world unprivileged eBPF |
| program is very small for this corner case. |
| |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Acked-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| kernel/bpf/verifier.c | 11 +++++++++++ |
| 1 file changed, 11 insertions(+) |
| |
| --- a/kernel/bpf/verifier.c |
| +++ b/kernel/bpf/verifier.c |
| @@ -2191,6 +2191,17 @@ static int adjust_ptr_min_max_vals(struc |
| __update_reg_bounds(dst_reg); |
| __reg_deduce_bounds(dst_reg); |
| __reg_bound_offset(dst_reg); |
| + |
| + /* For unprivileged we require that resulting offset must be in bounds |
| + * in order to be able to sanitize access later on. |
| + */ |
| + if (!env->allow_ptr_leaks && dst_reg->type == PTR_TO_MAP_VALUE && |
| + check_map_access(env, dst, dst_reg->off, 1, false)) { |
| + verbose(env, "R%d pointer arithmetic of map value goes out of range, prohibited for !root\n", |
| + dst); |
| + return -EACCES; |
| + } |
| + |
| return 0; |
| } |
| |