@@ -14187,82 +14187,104 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
14187
14187
u8 opcode, bool is_jmp32)
14188
14188
{
14189
14189
struct tnum t1 = is_jmp32 ? tnum_subreg(reg1->var_off) : reg1->var_off;
14190
+ struct tnum t2 = is_jmp32 ? tnum_subreg(reg2->var_off) : reg2->var_off;
14190
14191
u64 umin1 = is_jmp32 ? (u64)reg1->u32_min_value : reg1->umin_value;
14191
14192
u64 umax1 = is_jmp32 ? (u64)reg1->u32_max_value : reg1->umax_value;
14192
14193
s64 smin1 = is_jmp32 ? (s64)reg1->s32_min_value : reg1->smin_value;
14193
14194
s64 smax1 = is_jmp32 ? (s64)reg1->s32_max_value : reg1->smax_value;
14194
- u64 uval = is_jmp32 ? (u32)tnum_subreg(reg2->var_off).value : reg2->var_off.value;
14195
- s64 sval = is_jmp32 ? (s32)uval : (s64)uval;
14195
+ u64 umin2 = is_jmp32 ? (u64)reg2->u32_min_value : reg2->umin_value;
14196
+ u64 umax2 = is_jmp32 ? (u64)reg2->u32_max_value : reg2->umax_value;
14197
+ s64 smin2 = is_jmp32 ? (s64)reg2->s32_min_value : reg2->smin_value;
14198
+ s64 smax2 = is_jmp32 ? (s64)reg2->s32_max_value : reg2->smax_value;
14196
14199
14197
14200
switch (opcode) {
14198
14201
case BPF_JEQ:
14199
- if (tnum_is_const(t1))
14200
- return !!tnum_equals_const(t1, uval);
14201
- else if (uval < umin1 || uval > umax1)
14202
+ /* constants, umin/umax and smin/smax checks would be
14203
+ * redundant in this case because they all should match
14204
+ */
14205
+ if (tnum_is_const(t1) && tnum_is_const(t2))
14206
+ return t1.value == t2.value;
14207
+ /* const ranges */
14208
+ if (umin1 == umax1 && umin2 == umax2)
14209
+ return umin1 == umin2;
14210
+ if (smin1 == smax1 && smin2 == smax2)
14211
+ return smin1 == smin2;
14212
+ /* non-overlapping ranges */
14213
+ if (umin1 > umax2 || umax1 < umin2)
14202
14214
return 0;
14203
- else if (sval < smin1 || sval > smax1 )
14215
+ if (smin1 > smax2 || smax1 < smin2 )
14204
14216
return 0;
14205
14217
break;
14206
14218
case BPF_JNE:
14207
- if (tnum_is_const(t1))
14208
- return !tnum_equals_const(t1, uval);
14209
- else if (uval < umin1 || uval > umax1)
14219
+ /* constants, umin/umax and smin/smax checks would be
14220
+ * redundant in this case because they all should match
14221
+ */
14222
+ if (tnum_is_const(t1) && tnum_is_const(t2))
14223
+ return t1.value != t2.value;
14224
+ /* non-overlapping ranges */
14225
+ if (umin1 > umax2 || umax1 < umin2)
14210
14226
return 1;
14211
- else if (sval < smin1 || sval > smax1 )
14227
+ if (smin1 > smax2 || smax1 < smin2 )
14212
14228
return 1;
14213
14229
break;
14214
14230
case BPF_JSET:
14215
- if ((~t1.mask & t1.value) & uval)
14231
+ if (!is_reg_const(reg2, is_jmp32)) {
14232
+ swap(reg1, reg2);
14233
+ swap(t1, t2);
14234
+ }
14235
+ if (!is_reg_const(reg2, is_jmp32))
14236
+ return -1;
14237
+ if ((~t1.mask & t1.value) & t2.value)
14216
14238
return 1;
14217
- if (!((t1.mask | t1.value) & uval ))
14239
+ if (!((t1.mask | t1.value) & t2.value ))
14218
14240
return 0;
14219
14241
break;
14220
14242
case BPF_JGT:
14221
- if (umin1 > uval )
14243
+ if (umin1 > umax2 )
14222
14244
return 1;
14223
- else if (umax1 <= uval )
14245
+ else if (umax1 <= umin2 )
14224
14246
return 0;
14225
14247
break;
14226
14248
case BPF_JSGT:
14227
- if (smin1 > sval )
14249
+ if (smin1 > smax2 )
14228
14250
return 1;
14229
- else if (smax1 <= sval )
14251
+ else if (smax1 <= smin2 )
14230
14252
return 0;
14231
14253
break;
14232
14254
case BPF_JLT:
14233
- if (umax1 < uval )
14255
+ if (umax1 < umin2 )
14234
14256
return 1;
14235
- else if (umin1 >= uval )
14257
+ else if (umin1 >= umax2 )
14236
14258
return 0;
14237
14259
break;
14238
14260
case BPF_JSLT:
14239
- if (smax1 < sval )
14261
+ if (smax1 < smin2 )
14240
14262
return 1;
14241
- else if (smin1 >= sval )
14263
+ else if (smin1 >= smax2 )
14242
14264
return 0;
14243
14265
break;
14244
14266
case BPF_JGE:
14245
- if (umin1 >= uval )
14267
+ if (umin1 >= umax2 )
14246
14268
return 1;
14247
- else if (umax1 < uval )
14269
+ else if (umax1 < umin2 )
14248
14270
return 0;
14249
14271
break;
14250
14272
case BPF_JSGE:
14251
- if (smin1 >= sval )
14273
+ if (smin1 >= smax2 )
14252
14274
return 1;
14253
- else if (smax1 < sval )
14275
+ else if (smax1 < smin2 )
14254
14276
return 0;
14255
14277
break;
14256
14278
case BPF_JLE:
14257
- if (umax1 <= uval )
14279
+ if (umax1 <= umin2 )
14258
14280
return 1;
14259
- else if (umin1 > uval )
14281
+ else if (umin1 > umax2 )
14260
14282
return 0;
14261
14283
break;
14262
14284
case BPF_JSLE:
14263
- if (smax1 <= sval )
14285
+ if (smax1 <= smin2 )
14264
14286
return 1;
14265
- else if (smin1 > sval )
14287
+ else if (smin1 > smax2 )
14266
14288
return 0;
14267
14289
break;
14268
14290
}
@@ -14341,28 +14363,28 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
14341
14363
static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
14342
14364
u8 opcode, bool is_jmp32)
14343
14365
{
14344
- u64 val;
14345
-
14346
14366
if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
14347
14367
return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
14348
14368
14349
- /* try to make sure reg2 is a constant SCALAR_VALUE */
14350
- if (!is_reg_const(reg2, is_jmp32)) {
14351
- opcode = flip_opcode(opcode);
14352
- swap(reg1, reg2);
14353
- }
14354
- /* for now we expect reg2 to be a constant to make any useful decisions */
14355
- if (!is_reg_const(reg2, is_jmp32))
14356
- return -1;
14357
- val = reg_const_value(reg2, is_jmp32);
14369
+ if (__is_pointer_value(false, reg1) || __is_pointer_value(false, reg2)) {
14370
+ u64 val;
14371
+
14372
+ /* arrange that reg2 is a scalar, and reg1 is a pointer */
14373
+ if (!is_reg_const(reg2, is_jmp32)) {
14374
+ opcode = flip_opcode(opcode);
14375
+ swap(reg1, reg2);
14376
+ }
14377
+ /* and ensure that reg2 is a constant */
14378
+ if (!is_reg_const(reg2, is_jmp32))
14379
+ return -1;
14358
14380
14359
- if (__is_pointer_value(false, reg1)) {
14360
14381
if (!reg_not_null(reg1))
14361
14382
return -1;
14362
14383
14363
14384
/* If pointer is valid tests against zero will fail so we can
14364
14385
* use this to direct branch taken.
14365
14386
*/
14387
+ val = reg_const_value(reg2, is_jmp32);
14366
14388
if (val != 0)
14367
14389
return -1;
14368
14390
@@ -14376,6 +14398,7 @@ static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg
14376
14398
}
14377
14399
}
14378
14400
14401
+ /* now deal with two scalars, but not necessarily constants */
14379
14402
return is_scalar_branch_taken(reg1, reg2, opcode, is_jmp32);
14380
14403
}
14381
14404
0 commit comments