| From b658bbb844e28f1862867f37e8ca11a8e2aa94a3 Mon Sep 17 00:00:00 2001 |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| Date: Tue, 23 Mar 2021 09:04:10 +0100 |
| Subject: bpf: Rework ptr_limit into alu_limit and add common error path |
| |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| |
| commit b658bbb844e28f1862867f37e8ca11a8e2aa94a3 upstream. |
| |
| Small refactor with no semantic changes in order to consolidate the max |
| ptr_limit boundary check. |
| |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Reviewed-by: John Fastabend <john.fastabend@gmail.com> |
| Acked-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| kernel/bpf/verifier.c | 21 +++++++++++++-------- |
| 1 file changed, 13 insertions(+), 8 deletions(-) |
| |
| --- a/kernel/bpf/verifier.c |
| +++ b/kernel/bpf/verifier.c |
| @@ -5330,12 +5330,12 @@ static struct bpf_insn_aux_data *cur_aux |
| |
| static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, |
| const struct bpf_reg_state *off_reg, |
| - u32 *ptr_limit, u8 opcode) |
| + u32 *alu_limit, u8 opcode) |
| { |
| bool off_is_neg = off_reg->smin_value < 0; |
| bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || |
| (opcode == BPF_SUB && !off_is_neg); |
| - u32 off, max; |
| + u32 off, max = 0, ptr_limit = 0; |
| |
| if (!tnum_is_const(off_reg->var_off) && |
| (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) |
| @@ -5352,22 +5352,27 @@ static int retrieve_ptr_limit(const stru |
| */ |
| off = ptr_reg->off + ptr_reg->var_off.value; |
| if (mask_to_left) |
| - *ptr_limit = MAX_BPF_STACK + off; |
| + ptr_limit = MAX_BPF_STACK + off; |
| else |
| - *ptr_limit = -off - 1; |
| - return *ptr_limit >= max ? -ERANGE : 0; |
| + ptr_limit = -off - 1; |
| + break; |
| case PTR_TO_MAP_VALUE: |
| max = ptr_reg->map_ptr->value_size; |
| if (mask_to_left) { |
| - *ptr_limit = ptr_reg->umax_value + ptr_reg->off; |
| + ptr_limit = ptr_reg->umax_value + ptr_reg->off; |
| } else { |
| off = ptr_reg->smin_value + ptr_reg->off; |
| - *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; |
| + ptr_limit = ptr_reg->map_ptr->value_size - off - 1; |
| } |
| - return *ptr_limit >= max ? -ERANGE : 0; |
| + break; |
| default: |
| return -EINVAL; |
| } |
| + |
| + if (ptr_limit >= max) |
| + return -ERANGE; |
| + *alu_limit = ptr_limit; |
| + return 0; |
| } |
| |
| static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env, |