@@ -14187,82 +14187,104 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
1418714187 u8 opcode, bool is_jmp32)
1418814188{
1418914189 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;
1419014191 u64 umin1 = is_jmp32 ? (u64)reg1->u32_min_value : reg1->umin_value;
1419114192 u64 umax1 = is_jmp32 ? (u64)reg1->u32_max_value : reg1->umax_value;
1419214193 s64 smin1 = is_jmp32 ? (s64)reg1->s32_min_value : reg1->smin_value;
1419314194 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;
1419614199
1419714200 switch (opcode) {
1419814201 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)
1420214214 return 0;
14203- else if (sval < smin1 || sval > smax1 )
14215+ if (smin1 > smax2 || smax1 < smin2 )
1420414216 return 0;
1420514217 break;
1420614218 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)
1421014226 return 1;
14211- else if (sval < smin1 || sval > smax1 )
14227+ if (smin1 > smax2 || smax1 < smin2 )
1421214228 return 1;
1421314229 break;
1421414230 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)
1421614238 return 1;
14217- if (!((t1.mask | t1.value) & uval ))
14239+ if (!((t1.mask | t1.value) & t2.value ))
1421814240 return 0;
1421914241 break;
1422014242 case BPF_JGT:
14221- if (umin1 > uval )
14243+ if (umin1 > umax2 )
1422214244 return 1;
14223- else if (umax1 <= uval )
14245+ else if (umax1 <= umin2 )
1422414246 return 0;
1422514247 break;
1422614248 case BPF_JSGT:
14227- if (smin1 > sval )
14249+ if (smin1 > smax2 )
1422814250 return 1;
14229- else if (smax1 <= sval )
14251+ else if (smax1 <= smin2 )
1423014252 return 0;
1423114253 break;
1423214254 case BPF_JLT:
14233- if (umax1 < uval )
14255+ if (umax1 < umin2 )
1423414256 return 1;
14235- else if (umin1 >= uval )
14257+ else if (umin1 >= umax2 )
1423614258 return 0;
1423714259 break;
1423814260 case BPF_JSLT:
14239- if (smax1 < sval )
14261+ if (smax1 < smin2 )
1424014262 return 1;
14241- else if (smin1 >= sval )
14263+ else if (smin1 >= smax2 )
1424214264 return 0;
1424314265 break;
1424414266 case BPF_JGE:
14245- if (umin1 >= uval )
14267+ if (umin1 >= umax2 )
1424614268 return 1;
14247- else if (umax1 < uval )
14269+ else if (umax1 < umin2 )
1424814270 return 0;
1424914271 break;
1425014272 case BPF_JSGE:
14251- if (smin1 >= sval )
14273+ if (smin1 >= smax2 )
1425214274 return 1;
14253- else if (smax1 < sval )
14275+ else if (smax1 < smin2 )
1425414276 return 0;
1425514277 break;
1425614278 case BPF_JLE:
14257- if (umax1 <= uval )
14279+ if (umax1 <= umin2 )
1425814280 return 1;
14259- else if (umin1 > uval )
14281+ else if (umin1 > umax2 )
1426014282 return 0;
1426114283 break;
1426214284 case BPF_JSLE:
14263- if (smax1 <= sval )
14285+ if (smax1 <= smin2 )
1426414286 return 1;
14265- else if (smin1 > sval )
14287+ else if (smin1 > smax2 )
1426614288 return 0;
1426714289 break;
1426814290 }
@@ -14341,28 +14363,28 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
1434114363static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
1434214364 u8 opcode, bool is_jmp32)
1434314365{
14344- u64 val;
14345-
1434614366 if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
1434714367 return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
1434814368
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;
1435814380
14359- if (__is_pointer_value(false, reg1)) {
1436014381 if (!reg_not_null(reg1))
1436114382 return -1;
1436214383
1436314384 /* If pointer is valid tests against zero will fail so we can
1436414385 * use this to direct branch taken.
1436514386 */
14387+ val = reg_const_value(reg2, is_jmp32);
1436614388 if (val != 0)
1436714389 return -1;
1436814390
@@ -14376,6 +14398,7 @@ static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg
1437614398 }
1437714399 }
1437814400
14401+ /* now deal with two scalars, but not necessarily constants */
1437914402 return is_scalar_branch_taken(reg1, reg2, opcode, is_jmp32);
1438014403}
1438114404
0 commit comments