@@ -14261,82 +14261,99 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
14261
14261
u8 opcode, bool is_jmp32)
14262
14262
{
14263
14263
struct tnum t1 = is_jmp32 ? tnum_subreg(reg1->var_off) : reg1->var_off;
14264
+ struct tnum t2 = is_jmp32 ? tnum_subreg(reg2->var_off) : reg2->var_off;
14264
14265
u64 umin1 = is_jmp32 ? (u64)reg1->u32_min_value : reg1->umin_value;
14265
14266
u64 umax1 = is_jmp32 ? (u64)reg1->u32_max_value : reg1->umax_value;
14266
14267
s64 smin1 = is_jmp32 ? (s64)reg1->s32_min_value : reg1->smin_value;
14267
14268
s64 smax1 = is_jmp32 ? (s64)reg1->s32_max_value : reg1->smax_value;
14268
- u64 uval = is_jmp32 ? (u32)tnum_subreg(reg2->var_off).value : reg2->var_off.value;
14269
- s64 sval = is_jmp32 ? (s32)uval : (s64)uval;
14269
+ u64 umin2 = is_jmp32 ? (u64)reg2->u32_min_value : reg2->umin_value;
14270
+ u64 umax2 = is_jmp32 ? (u64)reg2->u32_max_value : reg2->umax_value;
14271
+ s64 smin2 = is_jmp32 ? (s64)reg2->s32_min_value : reg2->smin_value;
14272
+ s64 smax2 = is_jmp32 ? (s64)reg2->s32_max_value : reg2->smax_value;
14270
14273
14271
14274
switch (opcode) {
14272
14275
case BPF_JEQ:
14273
- if (tnum_is_const(t1))
14274
- return !!tnum_equals_const(t1, uval);
14275
- else if (uval < umin1 || uval > umax1)
14276
+ /* constants, umin/umax and smin/smax checks would be
14277
+ * redundant in this case because they all should match
14278
+ */
14279
+ if (tnum_is_const(t1) && tnum_is_const(t2))
14280
+ return t1.value == t2.value;
14281
+ /* non-overlapping ranges */
14282
+ if (umin1 > umax2 || umax1 < umin2)
14276
14283
return 0;
14277
- else if (sval < smin1 || sval > smax1 )
14284
+ if (smin1 > smax2 || smax1 < smin2 )
14278
14285
return 0;
14279
14286
break;
14280
14287
case BPF_JNE:
14281
- if (tnum_is_const(t1))
14282
- return !tnum_equals_const(t1, uval);
14283
- else if (uval < umin1 || uval > umax1)
14288
+ /* constants, umin/umax and smin/smax checks would be
14289
+ * redundant in this case because they all should match
14290
+ */
14291
+ if (tnum_is_const(t1) && tnum_is_const(t2))
14292
+ return t1.value != t2.value;
14293
+ /* non-overlapping ranges */
14294
+ if (umin1 > umax2 || umax1 < umin2)
14284
14295
return 1;
14285
- else if (sval < smin1 || sval > smax1 )
14296
+ if (smin1 > smax2 || smax1 < smin2 )
14286
14297
return 1;
14287
14298
break;
14288
14299
case BPF_JSET:
14289
- if ((~t1.mask & t1.value) & uval)
14300
+ if (!is_reg_const(reg2, is_jmp32)) {
14301
+ swap(reg1, reg2);
14302
+ swap(t1, t2);
14303
+ }
14304
+ if (!is_reg_const(reg2, is_jmp32))
14305
+ return -1;
14306
+ if ((~t1.mask & t1.value) & t2.value)
14290
14307
return 1;
14291
- if (!((t1.mask | t1.value) & uval ))
14308
+ if (!((t1.mask | t1.value) & t2.value ))
14292
14309
return 0;
14293
14310
break;
14294
14311
case BPF_JGT:
14295
- if (umin1 > uval )
14312
+ if (umin1 > umax2 )
14296
14313
return 1;
14297
- else if (umax1 <= uval )
14314
+ else if (umax1 <= umin2 )
14298
14315
return 0;
14299
14316
break;
14300
14317
case BPF_JSGT:
14301
- if (smin1 > sval )
14318
+ if (smin1 > smax2 )
14302
14319
return 1;
14303
- else if (smax1 <= sval )
14320
+ else if (smax1 <= smin2 )
14304
14321
return 0;
14305
14322
break;
14306
14323
case BPF_JLT:
14307
- if (umax1 < uval )
14324
+ if (umax1 < umin2 )
14308
14325
return 1;
14309
- else if (umin1 >= uval )
14326
+ else if (umin1 >= umax2 )
14310
14327
return 0;
14311
14328
break;
14312
14329
case BPF_JSLT:
14313
- if (smax1 < sval )
14330
+ if (smax1 < smin2 )
14314
14331
return 1;
14315
- else if (smin1 >= sval )
14332
+ else if (smin1 >= smax2 )
14316
14333
return 0;
14317
14334
break;
14318
14335
case BPF_JGE:
14319
- if (umin1 >= uval )
14336
+ if (umin1 >= umax2 )
14320
14337
return 1;
14321
- else if (umax1 < uval )
14338
+ else if (umax1 < umin2 )
14322
14339
return 0;
14323
14340
break;
14324
14341
case BPF_JSGE:
14325
- if (smin1 >= sval )
14342
+ if (smin1 >= smax2 )
14326
14343
return 1;
14327
- else if (smax1 < sval )
14344
+ else if (smax1 < smin2 )
14328
14345
return 0;
14329
14346
break;
14330
14347
case BPF_JLE:
14331
- if (umax1 <= uval )
14348
+ if (umax1 <= umin2 )
14332
14349
return 1;
14333
- else if (umin1 > uval )
14350
+ else if (umin1 > umax2 )
14334
14351
return 0;
14335
14352
break;
14336
14353
case BPF_JSLE:
14337
- if (smax1 <= sval )
14354
+ if (smax1 <= smin2 )
14338
14355
return 1;
14339
- else if (smin1 > sval )
14356
+ else if (smin1 > smax2 )
14340
14357
return 0;
14341
14358
break;
14342
14359
}
@@ -14415,28 +14432,28 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
14415
14432
static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
14416
14433
u8 opcode, bool is_jmp32)
14417
14434
{
14418
- u64 val;
14419
-
14420
14435
if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
14421
14436
return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
14422
14437
14423
- /* try to make sure reg2 is a constant SCALAR_VALUE */
14424
- if (!is_reg_const(reg2, is_jmp32)) {
14425
- opcode = flip_opcode(opcode);
14426
- swap(reg1, reg2);
14427
- }
14428
- /* for now we expect reg2 to be a constant to make any useful decisions */
14429
- if (!is_reg_const(reg2, is_jmp32))
14430
- return -1;
14431
- val = reg_const_value(reg2, is_jmp32);
14438
+ if (__is_pointer_value(false, reg1) || __is_pointer_value(false, reg2)) {
14439
+ u64 val;
14440
+
14441
+ /* arrange that reg2 is a scalar, and reg1 is a pointer */
14442
+ if (!is_reg_const(reg2, is_jmp32)) {
14443
+ opcode = flip_opcode(opcode);
14444
+ swap(reg1, reg2);
14445
+ }
14446
+ /* and ensure that reg2 is a constant */
14447
+ if (!is_reg_const(reg2, is_jmp32))
14448
+ return -1;
14432
14449
14433
- if (__is_pointer_value(false, reg1)) {
14434
14450
if (!reg_not_null(reg1))
14435
14451
return -1;
14436
14452
14437
14453
/* If pointer is valid tests against zero will fail so we can
14438
14454
* use this to direct branch taken.
14439
14455
*/
14456
+ val = reg_const_value(reg2, is_jmp32);
14440
14457
if (val != 0)
14441
14458
return -1;
14442
14459
@@ -14450,6 +14467,7 @@ static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg
14450
14467
}
14451
14468
}
14452
14469
14470
+ /* now deal with two scalars, but not necessarily constants */
14453
14471
return is_scalar_branch_taken(reg1, reg2, opcode, is_jmp32);
14454
14472
}
14455
14473
0 commit comments