Small refactor with no semantic changes in order to consolidate the max ptr_limit boundary check.
Unified · Split
| @@ -5858,12 +5858,12 @@ static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env) · 5857 unmodified lines | |||
| 5858 | 5858 | ||
| 5859 | static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, | 5859 | static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, |
| 5860 | const struct bpf_reg_state *off_reg, | 5860 | const struct bpf_reg_state *off_reg, |
| 5861 | u32 *ptr_limit, u8 opcode) | 5861 | u32 *alu_limit, u8 opcode) |
| 5862 | { | 5862 | { |
| 5863 | bool off_is_neg = off_reg->smin_value < 0; | 5863 | bool off_is_neg = off_reg->smin_value < 0; |
| 5864 | bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || | 5864 | bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || |
| 5865 | (opcode == BPF_SUB && !off_is_neg); | 5865 | (opcode == BPF_SUB && !off_is_neg); |
| 5866 | u32 off, max; | 5866 | u32 off, max = 0, ptr_limit = 0; |
| 5867 | 5867 | ||
| 5868 | if (!tnum_is_const(off_reg->var_off) && | 5868 | if (!tnum_is_const(off_reg->var_off) && |
| 5869 | (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) | 5869 | (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) |
| @@ -5880,22 +5880,27 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, · 10 unmodified lines | |||
| 5880 | */ | 5880 | */ |
| 5881 | off = ptr_reg->off + ptr_reg->var_off.value; | 5881 | off = ptr_reg->off + ptr_reg->var_off.value; |
| 5882 | if (mask_to_left) | 5882 | if (mask_to_left) |
| 5883 | *ptr_limit = MAX_BPF_STACK + off; | 5883 | ptr_limit = MAX_BPF_STACK + off; |
| 5884 | else | 5884 | else |
| 5885 | *ptr_limit = -off - 1; | 5885 | ptr_limit = -off - 1; |
| 5886 | return *ptr_limit >= max ? -ERANGE : 0; | 5886 | break; |
| 5887 | case PTR_TO_MAP_VALUE: | 5887 | case PTR_TO_MAP_VALUE: |
| 5888 | max = ptr_reg->map_ptr->value_size; | 5888 | max = ptr_reg->map_ptr->value_size; |
| 5889 | if (mask_to_left) { | 5889 | if (mask_to_left) { |
| 5890 | *ptr_limit = ptr_reg->umax_value + ptr_reg->off; | 5890 | ptr_limit = ptr_reg->umax_value + ptr_reg->off; |
| 5891 | } else { | 5891 | } else { |
| 5892 | off = ptr_reg->smin_value + ptr_reg->off; | 5892 | off = ptr_reg->smin_value + ptr_reg->off; |
| 5893 | *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; | 5893 | ptr_limit = ptr_reg->map_ptr->value_size - off - 1; |
| 5894 | } | 5894 | } |
| 5895 | return *ptr_limit >= max ? -ERANGE : 0; | 5895 | break; |
| 5896 | default: | 5896 | default: |
| 5897 | return -EINVAL; | 5897 | return -EINVAL; |
| 5898 | } | 5898 | } |
| 5899 | |||
| 5900 | if (ptr_limit >= max) | ||
| 5901 | return -ERANGE; | ||
| 5902 | *alu_limit = ptr_limit; | ||
| 5903 | return 0; | ||
| 5899 | } | 5904 | } |
| 5900 | 5905 | ||
| 5901 | static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env, | 5906 | static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env, |