@@ -14261,82 +14261,99 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
1426114261 u8 opcode, bool is_jmp32)
1426214262{
1426314263 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;
1426414265 u64 umin1 = is_jmp32 ? (u64)reg1->u32_min_value : reg1->umin_value;
1426514266 u64 umax1 = is_jmp32 ? (u64)reg1->u32_max_value : reg1->umax_value;
1426614267 s64 smin1 = is_jmp32 ? (s64)reg1->s32_min_value : reg1->smin_value;
1426714268 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;
1427014273
1427114274 switch (opcode) {
1427214275 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)
1427614283 return 0;
14277- else if (sval < smin1 || sval > smax1 )
14284+ if (smin1 > smax2 || smax1 < smin2 )
1427814285 return 0;
1427914286 break;
1428014287 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)
1428414295 return 1;
14285- else if (sval < smin1 || sval > smax1 )
14296+ if (smin1 > smax2 || smax1 < smin2 )
1428614297 return 1;
1428714298 break;
1428814299 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)
1429014307 return 1;
14291- if (!((t1.mask | t1.value) & uval ))
14308+ if (!((t1.mask | t1.value) & t2.value ))
1429214309 return 0;
1429314310 break;
1429414311 case BPF_JGT:
14295- if (umin1 > uval )
14312+ if (umin1 > umax2 )
1429614313 return 1;
14297- else if (umax1 <= uval )
14314+ else if (umax1 <= umin2 )
1429814315 return 0;
1429914316 break;
1430014317 case BPF_JSGT:
14301- if (smin1 > sval )
14318+ if (smin1 > smax2 )
1430214319 return 1;
14303- else if (smax1 <= sval )
14320+ else if (smax1 <= smin2 )
1430414321 return 0;
1430514322 break;
1430614323 case BPF_JLT:
14307- if (umax1 < uval )
14324+ if (umax1 < umin2 )
1430814325 return 1;
14309- else if (umin1 >= uval )
14326+ else if (umin1 >= umax2 )
1431014327 return 0;
1431114328 break;
1431214329 case BPF_JSLT:
14313- if (smax1 < sval )
14330+ if (smax1 < smin2 )
1431414331 return 1;
14315- else if (smin1 >= sval )
14332+ else if (smin1 >= smax2 )
1431614333 return 0;
1431714334 break;
1431814335 case BPF_JGE:
14319- if (umin1 >= uval )
14336+ if (umin1 >= umax2 )
1432014337 return 1;
14321- else if (umax1 < uval )
14338+ else if (umax1 < umin2 )
1432214339 return 0;
1432314340 break;
1432414341 case BPF_JSGE:
14325- if (smin1 >= sval )
14342+ if (smin1 >= smax2 )
1432614343 return 1;
14327- else if (smax1 < sval )
14344+ else if (smax1 < smin2 )
1432814345 return 0;
1432914346 break;
1433014347 case BPF_JLE:
14331- if (umax1 <= uval )
14348+ if (umax1 <= umin2 )
1433214349 return 1;
14333- else if (umin1 > uval )
14350+ else if (umin1 > umax2 )
1433414351 return 0;
1433514352 break;
1433614353 case BPF_JSLE:
14337- if (smax1 <= sval )
14354+ if (smax1 <= smin2 )
1433814355 return 1;
14339- else if (smin1 > sval )
14356+ else if (smin1 > smax2 )
1434014357 return 0;
1434114358 break;
1434214359 }
@@ -14415,28 +14432,28 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
1441514432static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
1441614433 u8 opcode, bool is_jmp32)
1441714434{
14418- u64 val;
14419-
1442014435 if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
1442114436 return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
1442214437
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;
1443214449
14433- if (__is_pointer_value(false, reg1)) {
1443414450 if (!reg_not_null(reg1))
1443514451 return -1;
1443614452
1443714453 /* If pointer is valid tests against zero will fail so we can
1443814454 * use this to direct branch taken.
1443914455 */
14456+ val = reg_const_value(reg2, is_jmp32);
1444014457 if (val != 0)
1444114458 return -1;
1444214459
@@ -14450,6 +14467,7 @@ static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg
1445014467 }
1445114468 }
1445214469
14470+ /* now deal with two scalars, but not necessarily constants */
1445314471 return is_scalar_branch_taken(reg1, reg2, opcode, is_jmp32);
1445414472}
1445514473
0 commit comments