Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Verifer, refactor adjust_scalar_min_max_vals

Pull per op ALU logic into individual functions. We are about to add
u32 versions of each of these by pull them out the code gets a bit
more readable here and nicer in the next patch.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/158507149518.15666.15672349629329072411.stgit@john-Precision-5820-Tower

authored by

John Fastabend and committed by
Alexei Starovoitov
07cd2631 8395f320

+239 -164
+239 -164
kernel/bpf/verifier.c
··· 4843 4843 return 0; 4844 4844 } 4845 4845 4846 + static void scalar_min_max_add(struct bpf_reg_state *dst_reg, 4847 + struct bpf_reg_state *src_reg) 4848 + { 4849 + s64 smin_val = src_reg->smin_value; 4850 + s64 smax_val = src_reg->smax_value; 4851 + u64 umin_val = src_reg->umin_value; 4852 + u64 umax_val = src_reg->umax_value; 4853 + 4854 + if (signed_add_overflows(dst_reg->smin_value, smin_val) || 4855 + signed_add_overflows(dst_reg->smax_value, smax_val)) { 4856 + dst_reg->smin_value = S64_MIN; 4857 + dst_reg->smax_value = S64_MAX; 4858 + } else { 4859 + dst_reg->smin_value += smin_val; 4860 + dst_reg->smax_value += smax_val; 4861 + } 4862 + if (dst_reg->umin_value + umin_val < umin_val || 4863 + dst_reg->umax_value + umax_val < umax_val) { 4864 + dst_reg->umin_value = 0; 4865 + dst_reg->umax_value = U64_MAX; 4866 + } else { 4867 + dst_reg->umin_value += umin_val; 4868 + dst_reg->umax_value += umax_val; 4869 + } 4870 + dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg->var_off); 4871 + } 4872 + 4873 + static void scalar_min_max_sub(struct bpf_reg_state *dst_reg, 4874 + struct bpf_reg_state *src_reg) 4875 + { 4876 + s64 smin_val = src_reg->smin_value; 4877 + s64 smax_val = src_reg->smax_value; 4878 + u64 umin_val = src_reg->umin_value; 4879 + u64 umax_val = src_reg->umax_value; 4880 + 4881 + if (signed_sub_overflows(dst_reg->smin_value, smax_val) || 4882 + signed_sub_overflows(dst_reg->smax_value, smin_val)) { 4883 + /* Overflow possible, we know nothing */ 4884 + dst_reg->smin_value = S64_MIN; 4885 + dst_reg->smax_value = S64_MAX; 4886 + } else { 4887 + dst_reg->smin_value -= smax_val; 4888 + dst_reg->smax_value -= smin_val; 4889 + } 4890 + if (dst_reg->umin_value < umax_val) { 4891 + /* Overflow possible, we know nothing */ 4892 + dst_reg->umin_value = 0; 4893 + dst_reg->umax_value = U64_MAX; 4894 + } else { 4895 + /* Cannot overflow (as long as bounds are consistent) */ 4896 + dst_reg->umin_value -= umax_val; 4897 + dst_reg->umax_value -= umin_val; 4898 + } 4899 + dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg->var_off); 4900 + } 4901 + 4902 + static void scalar_min_max_mul(struct bpf_reg_state *dst_reg, 4903 + struct bpf_reg_state *src_reg) 4904 + { 4905 + s64 smin_val = src_reg->smin_value; 4906 + u64 umin_val = src_reg->umin_value; 4907 + u64 umax_val = src_reg->umax_value; 4908 + 4909 + dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg->var_off); 4910 + if (smin_val < 0 || dst_reg->smin_value < 0) { 4911 + /* Ain't nobody got time to multiply that sign */ 4912 + __mark_reg_unbounded(dst_reg); 4913 + __update_reg_bounds(dst_reg); 4914 + return; 4915 + } 4916 + /* Both values are positive, so we can work with unsigned and 4917 + * copy the result to signed (unless it exceeds S64_MAX). 4918 + */ 4919 + if (umax_val > U32_MAX || dst_reg->umax_value > U32_MAX) { 4920 + /* Potential overflow, we know nothing */ 4921 + __mark_reg_unbounded(dst_reg); 4922 + /* (except what we can learn from the var_off) */ 4923 + __update_reg_bounds(dst_reg); 4924 + return; 4925 + } 4926 + dst_reg->umin_value *= umin_val; 4927 + dst_reg->umax_value *= umax_val; 4928 + if (dst_reg->umax_value > S64_MAX) { 4929 + /* Overflow possible, we know nothing */ 4930 + dst_reg->smin_value = S64_MIN; 4931 + dst_reg->smax_value = S64_MAX; 4932 + } else { 4933 + dst_reg->smin_value = dst_reg->umin_value; 4934 + dst_reg->smax_value = dst_reg->umax_value; 4935 + } 4936 + } 4937 + 4938 + static void scalar_min_max_and(struct bpf_reg_state *dst_reg, 4939 + struct bpf_reg_state *src_reg) 4940 + { 4941 + s64 smin_val = src_reg->smin_value; 4942 + u64 umax_val = src_reg->umax_value; 4943 + 4944 + /* We get our minimum from the var_off, since that's inherently 4945 + * bitwise. Our maximum is the minimum of the operands' maxima. 4946 + */ 4947 + dst_reg->var_off = tnum_and(dst_reg->var_off, src_reg->var_off); 4948 + dst_reg->umin_value = dst_reg->var_off.value; 4949 + dst_reg->umax_value = min(dst_reg->umax_value, umax_val); 4950 + if (dst_reg->smin_value < 0 || smin_val < 0) { 4951 + /* Lose signed bounds when ANDing negative numbers, 4952 + * ain't nobody got time for that. 4953 + */ 4954 + dst_reg->smin_value = S64_MIN; 4955 + dst_reg->smax_value = S64_MAX; 4956 + } else { 4957 + /* ANDing two positives gives a positive, so safe to 4958 + * cast result into s64. 4959 + */ 4960 + dst_reg->smin_value = dst_reg->umin_value; 4961 + dst_reg->smax_value = dst_reg->umax_value; 4962 + } 4963 + /* We may learn something more from the var_off */ 4964 + __update_reg_bounds(dst_reg); 4965 + } 4966 + 4967 + static void scalar_min_max_or(struct bpf_reg_state *dst_reg, 4968 + struct bpf_reg_state *src_reg) 4969 + { 4970 + s64 smin_val = src_reg->smin_value; 4971 + u64 umin_val = src_reg->umin_value; 4972 + 4973 + /* We get our maximum from the var_off, and our minimum is the 4974 + * maximum of the operands' minima 4975 + */ 4976 + dst_reg->var_off = tnum_or(dst_reg->var_off, src_reg->var_off); 4977 + dst_reg->umin_value = max(dst_reg->umin_value, umin_val); 4978 + dst_reg->umax_value = dst_reg->var_off.value | dst_reg->var_off.mask; 4979 + if (dst_reg->smin_value < 0 || smin_val < 0) { 4980 + /* Lose signed bounds when ORing negative numbers, 4981 + * ain't nobody got time for that. 4982 + */ 4983 + dst_reg->smin_value = S64_MIN; 4984 + dst_reg->smax_value = S64_MAX; 4985 + } else { 4986 + /* ORing two positives gives a positive, so safe to 4987 + * cast result into s64. 4988 + */ 4989 + dst_reg->smin_value = dst_reg->umin_value; 4990 + dst_reg->smax_value = dst_reg->umax_value; 4991 + } 4992 + /* We may learn something more from the var_off */ 4993 + __update_reg_bounds(dst_reg); 4994 + } 4995 + 4996 + static void scalar_min_max_lsh(struct bpf_reg_state *dst_reg, 4997 + struct bpf_reg_state *src_reg) 4998 + { 4999 + u64 umax_val = src_reg->umax_value; 5000 + u64 umin_val = src_reg->umin_value; 5001 + 5002 + /* We lose all sign bit information (except what we can pick 5003 + * up from var_off) 5004 + */ 5005 + dst_reg->smin_value = S64_MIN; 5006 + dst_reg->smax_value = S64_MAX; 5007 + /* If we might shift our top bit out, then we know nothing */ 5008 + if (dst_reg->umax_value > 1ULL << (63 - umax_val)) { 5009 + dst_reg->umin_value = 0; 5010 + dst_reg->umax_value = U64_MAX; 5011 + } else { 5012 + dst_reg->umin_value <<= umin_val; 5013 + dst_reg->umax_value <<= umax_val; 5014 + } 5015 + dst_reg->var_off = tnum_lshift(dst_reg->var_off, umin_val); 5016 + /* We may learn something more from the var_off */ 5017 + __update_reg_bounds(dst_reg); 5018 + } 5019 + 5020 + static void scalar_min_max_rsh(struct bpf_reg_state *dst_reg, 5021 + struct bpf_reg_state *src_reg) 5022 + { 5023 + u64 umax_val = src_reg->umax_value; 5024 + u64 umin_val = src_reg->umin_value; 5025 + 5026 + /* BPF_RSH is an unsigned shift. If the value in dst_reg might 5027 + * be negative, then either: 5028 + * 1) src_reg might be zero, so the sign bit of the result is 5029 + * unknown, so we lose our signed bounds 5030 + * 2) it's known negative, thus the unsigned bounds capture the 5031 + * signed bounds 5032 + * 3) the signed bounds cross zero, so they tell us nothing 5033 + * about the result 5034 + * If the value in dst_reg is known nonnegative, then again the 5035 + * unsigned bounts capture the signed bounds. 5036 + * Thus, in all cases it suffices to blow away our signed bounds 5037 + * and rely on inferring new ones from the unsigned bounds and 5038 + * var_off of the result. 5039 + */ 5040 + dst_reg->smin_value = S64_MIN; 5041 + dst_reg->smax_value = S64_MAX; 5042 + dst_reg->var_off = tnum_rshift(dst_reg->var_off, umin_val); 5043 + dst_reg->umin_value >>= umax_val; 5044 + dst_reg->umax_value >>= umin_val; 5045 + /* We may learn something more from the var_off */ 5046 + __update_reg_bounds(dst_reg); 5047 + } 5048 + 5049 + static void scalar_min_max_arsh(struct bpf_reg_state *dst_reg, 5050 + struct bpf_reg_state *src_reg, 5051 + u64 insn_bitness) 5052 + { 5053 + u64 umin_val = src_reg->umin_value; 5054 + 5055 + /* Upon reaching here, src_known is true and 5056 + * umax_val is equal to umin_val. 5057 + */ 5058 + if (insn_bitness == 32) { 5059 + dst_reg->smin_value = (u32)(((s32)dst_reg->smin_value) >> umin_val); 5060 + dst_reg->smax_value = (u32)(((s32)dst_reg->smax_value) >> umin_val); 5061 + } else { 5062 + dst_reg->smin_value >>= umin_val; 5063 + dst_reg->smax_value >>= umin_val; 5064 + } 5065 + 5066 + dst_reg->var_off = tnum_arshift(dst_reg->var_off, umin_val, 5067 + insn_bitness); 5068 + 5069 + /* blow away the dst_reg umin_value/umax_value and rely on 5070 + * dst_reg var_off to refine the result. 5071 + */ 5072 + dst_reg->umin_value = 0; 5073 + dst_reg->umax_value = U64_MAX; 5074 + __update_reg_bounds(dst_reg); 5075 + } 5076 + 4846 5077 /* WARNING: This function does calculations on 64-bit values, but the actual 4847 5078 * execution may occur on 32-bit values. Therefore, things like bitshifts 4848 5079 * need extra checks in the 32-bit case. ··· 5130 4899 verbose(env, "R%d tried to add from different pointers or scalars\n", dst); 5131 4900 return ret; 5132 4901 } 5133 - if (signed_add_overflows(dst_reg->smin_value, smin_val) || 5134 - signed_add_overflows(dst_reg->smax_value, smax_val)) { 5135 - dst_reg->smin_value = S64_MIN; 5136 - dst_reg->smax_value = S64_MAX; 5137 - } else { 5138 - dst_reg->smin_value += smin_val; 5139 - dst_reg->smax_value += smax_val; 5140 - } 5141 - if (dst_reg->umin_value + umin_val < umin_val || 5142 - dst_reg->umax_value + umax_val < umax_val) { 5143 - dst_reg->umin_value = 0; 5144 - dst_reg->umax_value = U64_MAX; 5145 - } else { 5146 - dst_reg->umin_value += umin_val; 5147 - dst_reg->umax_value += umax_val; 5148 - } 5149 - dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off); 4902 + scalar_min_max_add(dst_reg, &src_reg); 5150 4903 break; 5151 4904 case BPF_SUB: 5152 4905 ret = sanitize_val_alu(env, insn); ··· 5138 4923 verbose(env, "R%d tried to sub from different pointers or scalars\n", dst); 5139 4924 return ret; 5140 4925 } 5141 - if (signed_sub_overflows(dst_reg->smin_value, smax_val) || 5142 - signed_sub_overflows(dst_reg->smax_value, smin_val)) { 5143 - /* Overflow possible, we know nothing */ 5144 - dst_reg->smin_value = S64_MIN; 5145 - dst_reg->smax_value = S64_MAX; 5146 - } else { 5147 - dst_reg->smin_value -= smax_val; 5148 - dst_reg->smax_value -= smin_val; 5149 - } 5150 - if (dst_reg->umin_value < umax_val) { 5151 - /* Overflow possible, we know nothing */ 5152 - dst_reg->umin_value = 0; 5153 - dst_reg->umax_value = U64_MAX; 5154 - } else { 5155 - /* Cannot overflow (as long as bounds are consistent) */ 5156 - dst_reg->umin_value -= umax_val; 5157 - dst_reg->umax_value -= umin_val; 5158 - } 5159 - dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off); 4926 + scalar_min_max_sub(dst_reg, &src_reg); 5160 4927 break; 5161 4928 case BPF_MUL: 5162 - dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off); 5163 - if (smin_val < 0 || dst_reg->smin_value < 0) { 5164 - /* Ain't nobody got time to multiply that sign */ 5165 - __mark_reg_unbounded(dst_reg); 5166 - __update_reg_bounds(dst_reg); 5167 - break; 5168 - } 5169 - /* Both values are positive, so we can work with unsigned and 5170 - * copy the result to signed (unless it exceeds S64_MAX). 5171 - */ 5172 - if (umax_val > U32_MAX || dst_reg->umax_value > U32_MAX) { 5173 - /* Potential overflow, we know nothing */ 5174 - __mark_reg_unbounded(dst_reg); 5175 - /* (except what we can learn from the var_off) */ 5176 - __update_reg_bounds(dst_reg); 5177 - break; 5178 - } 5179 - dst_reg->umin_value *= umin_val; 5180 - dst_reg->umax_value *= umax_val; 5181 - if (dst_reg->umax_value > S64_MAX) { 5182 - /* Overflow possible, we know nothing */ 5183 - dst_reg->smin_value = S64_MIN; 5184 - dst_reg->smax_value = S64_MAX; 5185 - } else { 5186 - dst_reg->smin_value = dst_reg->umin_value; 5187 - dst_reg->smax_value = dst_reg->umax_value; 5188 - } 4929 + scalar_min_max_mul(dst_reg, &src_reg); 5189 4930 break; 5190 4931 case BPF_AND: 5191 4932 if (src_known && dst_known) { ··· 5149 4978 src_reg.var_off.value); 5150 4979 break; 5151 4980 } 5152 - /* We get our minimum from the var_off, since that's inherently 5153 - * bitwise. Our maximum is the minimum of the operands' maxima. 5154 - */ 5155 - dst_reg->var_off = tnum_and(dst_reg->var_off, src_reg.var_off); 5156 - dst_reg->umin_value = dst_reg->var_off.value; 5157 - dst_reg->umax_value = min(dst_reg->umax_value, umax_val); 5158 - if (dst_reg->smin_value < 0 || smin_val < 0) { 5159 - /* Lose signed bounds when ANDing negative numbers, 5160 - * ain't nobody got time for that. 5161 - */ 5162 - dst_reg->smin_value = S64_MIN; 5163 - dst_reg->smax_value = S64_MAX; 5164 - } else { 5165 - /* ANDing two positives gives a positive, so safe to 5166 - * cast result into s64. 5167 - */ 5168 - dst_reg->smin_value = dst_reg->umin_value; 5169 - dst_reg->smax_value = dst_reg->umax_value; 5170 - } 5171 - /* We may learn something more from the var_off */ 5172 - __update_reg_bounds(dst_reg); 4981 + scalar_min_max_and(dst_reg, &src_reg); 5173 4982 break; 5174 4983 case BPF_OR: 5175 4984 if (src_known && dst_known) { ··· 5157 5006 src_reg.var_off.value); 5158 5007 break; 5159 5008 } 5160 - /* We get our maximum from the var_off, and our minimum is the 5161 - * maximum of the operands' minima 5162 - */ 5163 - dst_reg->var_off = tnum_or(dst_reg->var_off, src_reg.var_off); 5164 - dst_reg->umin_value = max(dst_reg->umin_value, umin_val); 5165 - dst_reg->umax_value = dst_reg->var_off.value | 5166 - dst_reg->var_off.mask; 5167 - if (dst_reg->smin_value < 0 || smin_val < 0) { 5168 - /* Lose signed bounds when ORing negative numbers, 5169 - * ain't nobody got time for that. 5170 - */ 5171 - dst_reg->smin_value = S64_MIN; 5172 - dst_reg->smax_value = S64_MAX; 5173 - } else { 5174 - /* ORing two positives gives a positive, so safe to 5175 - * cast result into s64. 5176 - */ 5177 - dst_reg->smin_value = dst_reg->umin_value; 5178 - dst_reg->smax_value = dst_reg->umax_value; 5179 - } 5180 - /* We may learn something more from the var_off */ 5181 - __update_reg_bounds(dst_reg); 5009 + scalar_min_max_or(dst_reg, &src_reg); 5182 5010 break; 5183 5011 case BPF_LSH: 5184 5012 if (umax_val >= insn_bitness) { ··· 5167 5037 mark_reg_unknown(env, regs, insn->dst_reg); 5168 5038 break; 5169 5039 } 5170 - /* We lose all sign bit information (except what we can pick 5171 - * up from var_off) 5172 - */ 5173 - dst_reg->smin_value = S64_MIN; 5174 - dst_reg->smax_value = S64_MAX; 5175 - /* If we might shift our top bit out, then we know nothing */ 5176 - if (dst_reg->umax_value > 1ULL << (63 - umax_val)) { 5177 - dst_reg->umin_value = 0; 5178 - dst_reg->umax_value = U64_MAX; 5179 - } else { 5180 - dst_reg->umin_value <<= umin_val; 5181 - dst_reg->umax_value <<= umax_val; 5182 - } 5183 - dst_reg->var_off = tnum_lshift(dst_reg->var_off, umin_val); 5184 - /* We may learn something more from the var_off */ 5185 - __update_reg_bounds(dst_reg); 5040 + scalar_min_max_lsh(dst_reg, &src_reg); 5186 5041 break; 5187 5042 case BPF_RSH: 5188 5043 if (umax_val >= insn_bitness) { ··· 5177 5062 mark_reg_unknown(env, regs, insn->dst_reg); 5178 5063 break; 5179 5064 } 5180 - /* BPF_RSH is an unsigned shift. If the value in dst_reg might 5181 - * be negative, then either: 5182 - * 1) src_reg might be zero, so the sign bit of the result is 5183 - * unknown, so we lose our signed bounds 5184 - * 2) it's known negative, thus the unsigned bounds capture the 5185 - * signed bounds 5186 - * 3) the signed bounds cross zero, so they tell us nothing 5187 - * about the result 5188 - * If the value in dst_reg is known nonnegative, then again the 5189 - * unsigned bounts capture the signed bounds. 5190 - * Thus, in all cases it suffices to blow away our signed bounds 5191 - * and rely on inferring new ones from the unsigned bounds and 5192 - * var_off of the result. 5193 - */ 5194 - dst_reg->smin_value = S64_MIN; 5195 - dst_reg->smax_value = S64_MAX; 5196 - dst_reg->var_off = tnum_rshift(dst_reg->var_off, umin_val); 5197 - dst_reg->umin_value >>= umax_val; 5198 - dst_reg->umax_value >>= umin_val; 5199 - /* We may learn something more from the var_off */ 5200 - __update_reg_bounds(dst_reg); 5065 + scalar_min_max_rsh(dst_reg, &src_reg); 5201 5066 break; 5202 5067 case BPF_ARSH: 5203 5068 if (umax_val >= insn_bitness) { ··· 5187 5092 mark_reg_unknown(env, regs, insn->dst_reg); 5188 5093 break; 5189 5094 } 5190 - 5191 - /* Upon reaching here, src_known is true and 5192 - * umax_val is equal to umin_val. 5193 - */ 5194 - if (insn_bitness == 32) { 5195 - dst_reg->smin_value = (u32)(((s32)dst_reg->smin_value) >> umin_val); 5196 - dst_reg->smax_value = (u32)(((s32)dst_reg->smax_value) >> umin_val); 5197 - } else { 5198 - dst_reg->smin_value >>= umin_val; 5199 - dst_reg->smax_value >>= umin_val; 5200 - } 5201 - 5202 - dst_reg->var_off = tnum_arshift(dst_reg->var_off, umin_val, 5203 - insn_bitness); 5204 - 5205 - /* blow away the dst_reg umin_value/umax_value and rely on 5206 - * dst_reg var_off to refine the result. 5207 - */ 5208 - dst_reg->umin_value = 0; 5209 - dst_reg->umax_value = U64_MAX; 5210 - __update_reg_bounds(dst_reg); 5095 + scalar_min_max_arsh(dst_reg, &src_reg, insn_bitness); 5211 5096 break; 5212 5097 default: 5213 5098 mark_reg_unknown(env, regs, insn->dst_reg);