aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/bpf/verifier.c172
1 files changed, 99 insertions, 73 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8cfe39ef770f..eae6cb1fe653 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -4033,9 +4033,13 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
4033 */ 4033 */
4034static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode) 4034static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4035{ 4035{
4036 s64 sval;
4037
4036 if (__is_pointer_value(false, reg)) 4038 if (__is_pointer_value(false, reg))
4037 return -1; 4039 return -1;
4038 4040
4041 sval = (s64)val;
4042
4039 switch (opcode) { 4043 switch (opcode) {
4040 case BPF_JEQ: 4044 case BPF_JEQ:
4041 if (tnum_is_const(reg->var_off)) 4045 if (tnum_is_const(reg->var_off))
@@ -4058,9 +4062,9 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4058 return 0; 4062 return 0;
4059 break; 4063 break;
4060 case BPF_JSGT: 4064 case BPF_JSGT:
4061 if (reg->smin_value > (s64)val) 4065 if (reg->smin_value > sval)
4062 return 1; 4066 return 1;
4063 else if (reg->smax_value < (s64)val) 4067 else if (reg->smax_value < sval)
4064 return 0; 4068 return 0;
4065 break; 4069 break;
4066 case BPF_JLT: 4070 case BPF_JLT:
@@ -4070,9 +4074,9 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4070 return 0; 4074 return 0;
4071 break; 4075 break;
4072 case BPF_JSLT: 4076 case BPF_JSLT:
4073 if (reg->smax_value < (s64)val) 4077 if (reg->smax_value < sval)
4074 return 1; 4078 return 1;
4075 else if (reg->smin_value >= (s64)val) 4079 else if (reg->smin_value >= sval)
4076 return 0; 4080 return 0;
4077 break; 4081 break;
4078 case BPF_JGE: 4082 case BPF_JGE:
@@ -4082,9 +4086,9 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4082 return 0; 4086 return 0;
4083 break; 4087 break;
4084 case BPF_JSGE: 4088 case BPF_JSGE:
4085 if (reg->smin_value >= (s64)val) 4089 if (reg->smin_value >= sval)
4086 return 1; 4090 return 1;
4087 else if (reg->smax_value < (s64)val) 4091 else if (reg->smax_value < sval)
4088 return 0; 4092 return 0;
4089 break; 4093 break;
4090 case BPF_JLE: 4094 case BPF_JLE:
@@ -4094,9 +4098,9 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
4094 return 0; 4098 return 0;
4095 break; 4099 break;
4096 case BPF_JSLE: 4100 case BPF_JSLE:
4097 if (reg->smax_value <= (s64)val) 4101 if (reg->smax_value <= sval)
4098 return 1; 4102 return 1;
4099 else if (reg->smin_value > (s64)val) 4103 else if (reg->smin_value > sval)
4100 return 0; 4104 return 0;
4101 break; 4105 break;
4102 } 4106 }
@@ -4113,6 +4117,8 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4113 struct bpf_reg_state *false_reg, u64 val, 4117 struct bpf_reg_state *false_reg, u64 val,
4114 u8 opcode) 4118 u8 opcode)
4115{ 4119{
4120 s64 sval;
4121
4116 /* If the dst_reg is a pointer, we can't learn anything about its 4122 /* If the dst_reg is a pointer, we can't learn anything about its
4117 * variable offset from the compare (unless src_reg were a pointer into 4123 * variable offset from the compare (unless src_reg were a pointer into
4118 * the same object, but we don't bother with that. 4124 * the same object, but we don't bother with that.
@@ -4122,19 +4128,22 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4122 if (__is_pointer_value(false, false_reg)) 4128 if (__is_pointer_value(false, false_reg))
4123 return; 4129 return;
4124 4130
4131 sval = (s64)val;
4132
4125 switch (opcode) { 4133 switch (opcode) {
4126 case BPF_JEQ: 4134 case BPF_JEQ:
4127 /* If this is false then we know nothing Jon Snow, but if it is
4128 * true then we know for sure.
4129 */
4130 __mark_reg_known(true_reg, val);
4131 break;
4132 case BPF_JNE: 4135 case BPF_JNE:
4133 /* If this is true we know nothing Jon Snow, but if it is false 4136 {
4134 * we know the value for sure; 4137 struct bpf_reg_state *reg =
4138 opcode == BPF_JEQ ? true_reg : false_reg;
4139
4140 /* For BPF_JEQ, if this is false we know nothing Jon Snow, but
4141 * if it is true we know the value for sure. Likewise for
4142 * BPF_JNE.
4135 */ 4143 */
4136 __mark_reg_known(false_reg, val); 4144 __mark_reg_known(reg, val);
4137 break; 4145 break;
4146 }
4138 case BPF_JSET: 4147 case BPF_JSET:
4139 false_reg->var_off = tnum_and(false_reg->var_off, 4148 false_reg->var_off = tnum_and(false_reg->var_off,
4140 tnum_const(~val)); 4149 tnum_const(~val));
@@ -4142,38 +4151,46 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
4142 true_reg->var_off = tnum_or(true_reg->var_off, 4151 true_reg->var_off = tnum_or(true_reg->var_off,
4143 tnum_const(val)); 4152 tnum_const(val));
4144 break; 4153 break;
4145 case BPF_JGT:
4146 false_reg->umax_value = min(false_reg->umax_value, val);
4147 true_reg->umin_value = max(true_reg->umin_value, val + 1);
4148 break;
4149 case BPF_JSGT:
4150 false_reg->smax_value = min_t(s64, false_reg->smax_value, val);
4151 true_reg->smin_value = max_t(s64, true_reg->smin_value, val + 1);
4152 break;
4153 case BPF_JLT:
4154 false_reg->umin_value = max(false_reg->umin_value, val);
4155 true_reg->umax_value = min(true_reg->umax_value, val - 1);
4156 break;
4157 case BPF_JSLT:
4158 false_reg->smin_value = max_t(s64, false_reg->smin_value, val);
4159 true_reg->smax_value = min_t(s64, true_reg->smax_value, val - 1);
4160 break;
4161 case BPF_JGE: 4154 case BPF_JGE:
4162 false_reg->umax_value = min(false_reg->umax_value, val - 1); 4155 case BPF_JGT:
4163 true_reg->umin_value = max(true_reg->umin_value, val); 4156 {
4157 u64 false_umax = opcode == BPF_JGT ? val : val - 1;
4158 u64 true_umin = opcode == BPF_JGT ? val + 1 : val;
4159
4160 false_reg->umax_value = min(false_reg->umax_value, false_umax);
4161 true_reg->umin_value = max(true_reg->umin_value, true_umin);
4164 break; 4162 break;
4163 }
4165 case BPF_JSGE: 4164 case BPF_JSGE:
4166 false_reg->smax_value = min_t(s64, false_reg->smax_value, val - 1); 4165 case BPF_JSGT:
4167 true_reg->smin_value = max_t(s64, true_reg->smin_value, val); 4166 {
4167 s64 false_smax = opcode == BPF_JSGT ? sval : sval - 1;
4168 s64 true_smin = opcode == BPF_JSGT ? sval + 1 : sval;
4169
4170 false_reg->smax_value = min(false_reg->smax_value, false_smax);
4171 true_reg->smin_value = max(true_reg->smin_value, true_smin);
4168 break; 4172 break;
4173 }
4169 case BPF_JLE: 4174 case BPF_JLE:
4170 false_reg->umin_value = max(false_reg->umin_value, val + 1); 4175 case BPF_JLT:
4171 true_reg->umax_value = min(true_reg->umax_value, val); 4176 {
4177 u64 false_umin = opcode == BPF_JLT ? val : val + 1;
4178 u64 true_umax = opcode == BPF_JLT ? val - 1 : val;
4179
4180 false_reg->umin_value = max(false_reg->umin_value, false_umin);
4181 true_reg->umax_value = min(true_reg->umax_value, true_umax);
4172 break; 4182 break;
4183 }
4173 case BPF_JSLE: 4184 case BPF_JSLE:
4174 false_reg->smin_value = max_t(s64, false_reg->smin_value, val + 1); 4185 case BPF_JSLT:
4175 true_reg->smax_value = min_t(s64, true_reg->smax_value, val); 4186 {
4187 s64 false_smin = opcode == BPF_JSLT ? sval : sval + 1;
4188 s64 true_smax = opcode == BPF_JSLT ? sval - 1 : sval;
4189
4190 false_reg->smin_value = max(false_reg->smin_value, false_smin);
4191 true_reg->smax_value = min(true_reg->smax_value, true_smax);
4176 break; 4192 break;
4193 }
4177 default: 4194 default:
4178 break; 4195 break;
4179 } 4196 }
@@ -4198,22 +4215,23 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4198 struct bpf_reg_state *false_reg, u64 val, 4215 struct bpf_reg_state *false_reg, u64 val,
4199 u8 opcode) 4216 u8 opcode)
4200{ 4217{
4218 s64 sval;
4219
4201 if (__is_pointer_value(false, false_reg)) 4220 if (__is_pointer_value(false, false_reg))
4202 return; 4221 return;
4203 4222
4223 sval = (s64)val;
4224
4204 switch (opcode) { 4225 switch (opcode) {
4205 case BPF_JEQ: 4226 case BPF_JEQ:
4206 /* If this is false then we know nothing Jon Snow, but if it is
4207 * true then we know for sure.
4208 */
4209 __mark_reg_known(true_reg, val);
4210 break;
4211 case BPF_JNE: 4227 case BPF_JNE:
4212 /* If this is true we know nothing Jon Snow, but if it is false 4228 {
4213 * we know the value for sure; 4229 struct bpf_reg_state *reg =
4214 */ 4230 opcode == BPF_JEQ ? true_reg : false_reg;
4215 __mark_reg_known(false_reg, val); 4231
4232 __mark_reg_known(reg, val);
4216 break; 4233 break;
4234 }
4217 case BPF_JSET: 4235 case BPF_JSET:
4218 false_reg->var_off = tnum_and(false_reg->var_off, 4236 false_reg->var_off = tnum_and(false_reg->var_off,
4219 tnum_const(~val)); 4237 tnum_const(~val));
@@ -4221,38 +4239,46 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4221 true_reg->var_off = tnum_or(true_reg->var_off, 4239 true_reg->var_off = tnum_or(true_reg->var_off,
4222 tnum_const(val)); 4240 tnum_const(val));
4223 break; 4241 break;
4224 case BPF_JGT:
4225 true_reg->umax_value = min(true_reg->umax_value, val - 1);
4226 false_reg->umin_value = max(false_reg->umin_value, val);
4227 break;
4228 case BPF_JSGT:
4229 true_reg->smax_value = min_t(s64, true_reg->smax_value, val - 1);
4230 false_reg->smin_value = max_t(s64, false_reg->smin_value, val);
4231 break;
4232 case BPF_JLT:
4233 true_reg->umin_value = max(true_reg->umin_value, val + 1);
4234 false_reg->umax_value = min(false_reg->umax_value, val);
4235 break;
4236 case BPF_JSLT:
4237 true_reg->smin_value = max_t(s64, true_reg->smin_value, val + 1);
4238 false_reg->smax_value = min_t(s64, false_reg->smax_value, val);
4239 break;
4240 case BPF_JGE: 4242 case BPF_JGE:
4241 true_reg->umax_value = min(true_reg->umax_value, val); 4243 case BPF_JGT:
4242 false_reg->umin_value = max(false_reg->umin_value, val + 1); 4244 {
4245 u64 false_umin = opcode == BPF_JGT ? val : val + 1;
4246 u64 true_umax = opcode == BPF_JGT ? val - 1 : val;
4247
4248 false_reg->umin_value = max(false_reg->umin_value, false_umin);
4249 true_reg->umax_value = min(true_reg->umax_value, true_umax);
4243 break; 4250 break;
4251 }
4244 case BPF_JSGE: 4252 case BPF_JSGE:
4245 true_reg->smax_value = min_t(s64, true_reg->smax_value, val); 4253 case BPF_JSGT:
4246 false_reg->smin_value = max_t(s64, false_reg->smin_value, val + 1); 4254 {
4255 s64 false_smin = opcode == BPF_JSGT ? sval : sval + 1;
4256 s64 true_smax = opcode == BPF_JSGT ? sval - 1 : sval;
4257
4258 false_reg->smin_value = max(false_reg->smin_value, false_smin);
4259 true_reg->smax_value = min(true_reg->smax_value, true_smax);
4247 break; 4260 break;
4261 }
4248 case BPF_JLE: 4262 case BPF_JLE:
4249 true_reg->umin_value = max(true_reg->umin_value, val); 4263 case BPF_JLT:
4250 false_reg->umax_value = min(false_reg->umax_value, val - 1); 4264 {
4265 u64 false_umax = opcode == BPF_JLT ? val : val - 1;
4266 u64 true_umin = opcode == BPF_JLT ? val + 1 : val;
4267
4268 false_reg->umax_value = min(false_reg->umax_value, false_umax);
4269 true_reg->umin_value = max(true_reg->umin_value, true_umin);
4251 break; 4270 break;
4271 }
4252 case BPF_JSLE: 4272 case BPF_JSLE:
4253 true_reg->smin_value = max_t(s64, true_reg->smin_value, val); 4273 case BPF_JSLT:
4254 false_reg->smax_value = min_t(s64, false_reg->smax_value, val - 1); 4274 {
4275 s64 false_smax = opcode == BPF_JSLT ? sval : sval - 1;
4276 s64 true_smin = opcode == BPF_JSLT ? sval + 1 : sval;
4277
4278 false_reg->smax_value = min(false_reg->smax_value, false_smax);
4279 true_reg->smin_value = max(true_reg->smin_value, true_smin);
4255 break; 4280 break;
4281 }
4256 default: 4282 default:
4257 break; 4283 break;
4258 } 4284 }