@@ -14189,82 +14189,105 @@ static int is_scalar_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_sta
1418914189 u8 opcode, bool is_jmp32)
1419014190{
1419114191 struct tnum t1 = is_jmp32 ? tnum_subreg(reg1->var_off) : reg1->var_off;
14192+ struct tnum t2 = is_jmp32 ? tnum_subreg(reg2->var_off) : reg2->var_off;
1419214193 u64 umin1 = is_jmp32 ? (u64)reg1->u32_min_value : reg1->umin_value;
1419314194 u64 umax1 = is_jmp32 ? (u64)reg1->u32_max_value : reg1->umax_value;
1419414195 s64 smin1 = is_jmp32 ? (s64)reg1->s32_min_value : reg1->smin_value;
1419514196 s64 smax1 = is_jmp32 ? (s64)reg1->s32_max_value : reg1->smax_value;
14196- u64 val = is_jmp32 ? (u32)tnum_subreg(reg2->var_off).value : reg2->var_off.value;
14197- s64 sval = is_jmp32 ? (s32)val : (s64)val;
14197+ u64 umin2 = is_jmp32 ? (u64)reg2->u32_min_value : reg2->umin_value;
14198+ u64 umax2 = is_jmp32 ? (u64)reg2->u32_max_value : reg2->umax_value;
14199+ s64 smin2 = is_jmp32 ? (s64)reg2->s32_min_value : reg2->smin_value;
14200+ s64 smax2 = is_jmp32 ? (s64)reg2->s32_max_value : reg2->smax_value;
1419814201
1419914202 switch (opcode) {
1420014203 case BPF_JEQ:
14201- if (tnum_is_const(t1))
14202- return !!tnum_equals_const(t1, val);
14203- else if (val < umin1 || val > umax1)
14204+ /* const tnums */
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 umin1 == umin2;
14212+ /* non-overlapping ranges */
14213+ if (umin1 > umax2 || umax1 < umin2)
1420414214 return 0;
14205- else if (sval < smin1 || sval > smax1 )
14215+ if (smin1 > smax2 || smax1 < smin2 )
1420614216 return 0;
1420714217 break;
1420814218 case BPF_JNE:
14209- if (tnum_is_const(t1))
14210- return !tnum_equals_const(t1, val);
14211- else if (val < umin1 || val > umax1)
14219+ /* const tnums */
14220+ if (tnum_is_const(t1) && tnum_is_const(t2))
14221+ return t1.value != t2.value;
14222+ /* const ranges */
14223+ if (umin1 == umax1 && umin2 == umax2)
14224+ return umin1 != umin2;
14225+ if (smin1 == smax1 && smin2 == smax2)
14226+ return umin1 != umin2;
14227+ /* non-overlapping ranges */
14228+ if (umin1 > umax2 || umax1 < umin2)
1421214229 return 1;
14213- else if (sval < smin1 || sval > smax1 )
14230+ if (smin1 > smax2 || smax1 < smin2 )
1421414231 return 1;
1421514232 break;
1421614233 case BPF_JSET:
14217- if ((~t1.mask & t1.value) & val)
14234+ if (!is_reg_const(reg2, is_jmp32)) {
14235+ swap(reg1, reg2);
14236+ swap(t1, t2);
14237+ }
14238+ if (!is_reg_const(reg2, is_jmp32))
14239+ return -1;
14240+ if ((~t1.mask & t1.value) & t2.value)
1421814241 return 1;
14219- if (!((t1.mask | t1.value) & val ))
14242+ if (!((t1.mask | t1.value) & t2.value ))
1422014243 return 0;
1422114244 break;
1422214245 case BPF_JGT:
14223- if (umin1 > val )
14246+ if (umin1 > umax2 )
1422414247 return 1;
14225- else if (umax1 <= val )
14248+ else if (umax1 <= umin2 )
1422614249 return 0;
1422714250 break;
1422814251 case BPF_JSGT:
14229- if (smin1 > sval )
14252+ if (smin1 > smax2 )
1423014253 return 1;
14231- else if (smax1 <= sval )
14254+ else if (smax1 <= smin2 )
1423214255 return 0;
1423314256 break;
1423414257 case BPF_JLT:
14235- if (umax1 < val )
14258+ if (umax1 < umin2 )
1423614259 return 1;
14237- else if (umin1 >= val )
14260+ else if (umin1 >= umax2 )
1423814261 return 0;
1423914262 break;
1424014263 case BPF_JSLT:
14241- if (smax1 < sval )
14264+ if (smax1 < smin2 )
1424214265 return 1;
14243- else if (smin1 >= sval )
14266+ else if (smin1 >= smax2 )
1424414267 return 0;
1424514268 break;
1424614269 case BPF_JGE:
14247- if (umin1 >= val )
14270+ if (umin1 >= umax2 )
1424814271 return 1;
14249- else if (umax1 < val )
14272+ else if (umax1 < umin2 )
1425014273 return 0;
1425114274 break;
1425214275 case BPF_JSGE:
14253- if (smin1 >= sval )
14276+ if (smin1 >= smax2 )
1425414277 return 1;
14255- else if (smax1 < sval )
14278+ else if (smax1 < smin2 )
1425614279 return 0;
1425714280 break;
1425814281 case BPF_JLE:
14259- if (umax1 <= val )
14282+ if (umax1 <= umin2 )
1426014283 return 1;
14261- else if (umin1 > val )
14284+ else if (umin1 > umax2 )
1426214285 return 0;
1426314286 break;
1426414287 case BPF_JSLE:
14265- if (smax1 <= sval )
14288+ if (smax1 <= smin2 )
1426614289 return 1;
14267- else if (smin1 > sval )
14290+ else if (smin1 > smax2 )
1426814291 return 0;
1426914292 break;
1427014293 }
@@ -14343,28 +14366,28 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg,
1434314366static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2,
1434414367 u8 opcode, bool is_jmp32)
1434514368{
14346- u64 val;
14347-
1434814369 if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32)
1434914370 return is_pkt_ptr_branch_taken(reg1, reg2, opcode);
1435014371
14351- /* try to make sure reg2 is a constant SCALAR_VALUE */
14352- if (!is_reg_const(reg2, is_jmp32)) {
14353- opcode = flip_opcode(opcode);
14354- swap(reg1, reg2);
14355- }
14356- /* for now we expect reg2 to be a constant to make any useful decisions */
14357- if (!is_reg_const(reg2, is_jmp32))
14358- return -1;
14359- val = reg_const_value(reg2, is_jmp32);
14372+ if (__is_pointer_value(false, reg1) || __is_pointer_value(false, reg2)) {
14373+ u64 val;
14374+
14375+ /* arrange that reg2 is a scalar, and reg1 is a pointer */
14376+ if (!is_reg_const(reg2, is_jmp32)) {
14377+ opcode = flip_opcode(opcode);
14378+ swap(reg1, reg2);
14379+ }
14380+ /* and ensure that reg2 is a constant */
14381+ if (!is_reg_const(reg2, is_jmp32))
14382+ return -1;
1436014383
14361- if (__is_pointer_value(false, reg1)) {
1436214384 if (!reg_not_null(reg1))
1436314385 return -1;
1436414386
1436514387 /* If pointer is valid tests against zero will fail so we can
1436614388 * use this to direct branch taken.
1436714389 */
14390+ val = reg_const_value(reg2, is_jmp32);
1436814391 if (val != 0)
1436914392 return -1;
1437014393
@@ -14378,6 +14401,7 @@ static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg
1437814401 }
1437914402 }
1438014403
14404+ /* now deal with two scalars, but not necessarily constants */
1438114405 return is_scalar_branch_taken(reg1, reg2, opcode, is_jmp32);
1438214406}
1438314407
0 commit comments