On Fri, 2023-10-27 at 11:13 -0700, Andrii Nakryiko wrote: > > Make is_branch_taken() a single entry point for branch pruning decision > > making, handling both pointer vs pointer, pointer vs scalar, and scalar > > vs scalar cases in one place. This also nicely cleans up check_cond_jmp_op(). > > > > Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx> Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx> > > --- > > kernel/bpf/verifier.c | 49 ++++++++++++++++++++++--------------------- > > 1 file changed, 25 insertions(+), 24 deletions(-) > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > index 25b5234ebda3..fedd6d0e76e5 100644 > > --- a/kernel/bpf/verifier.c > > +++ b/kernel/bpf/verifier.c > > @@ -14169,6 +14169,19 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, > > })); > > } > > > > +/* check if register is a constant scalar value */ > > +static bool is_reg_const(struct bpf_reg_state *reg, bool subreg32) > > +{ > > + return reg->type == SCALAR_VALUE && > > + tnum_is_const(subreg32 ? tnum_subreg(reg->var_off) : reg->var_off); > > +} > > + > > +/* assuming is_reg_const() is true, return constant value of a register */ > > +static u64 reg_const_value(struct bpf_reg_state *reg, bool subreg32) > > +{ > > + return subreg32 ? tnum_subreg(reg->var_off).value : reg->var_off.value; > > +} > > + > > /* > > * <reg1> <op> <reg2>, currently assuming reg2 is a constant > > */ > > @@ -14410,12 +14423,20 @@ static int is_pkt_ptr_branch_taken(struct bpf_reg_state *dst_reg, > > static int is_branch_taken(struct bpf_reg_state *reg1, struct bpf_reg_state *reg2, > > u8 opcode, bool is_jmp32) > > { > > - struct tnum reg2_tnum = is_jmp32 ? tnum_subreg(reg2->var_off) : reg2->var_off; > > u64 val; > > > > - if (!tnum_is_const(reg2_tnum)) > > + if (reg_is_pkt_pointer_any(reg1) && reg_is_pkt_pointer_any(reg2) && !is_jmp32) > > + return is_pkt_ptr_branch_taken(reg1, reg2, opcode); > > + > > + /* try to make sure reg2 is a constant SCALAR_VALUE */ > > + if (!is_reg_const(reg2, is_jmp32)) { > > + opcode = flip_opcode(opcode); > > + swap(reg1, reg2); > > + } > > + /* for now we expect reg2 to be a constant to make any useful decisions */ > > + if (!is_reg_const(reg2, is_jmp32)) > > return -1; > > - val = reg2_tnum.value; > > + val = reg_const_value(reg2, is_jmp32); > > > > if (__is_pointer_value(false, reg1)) { > > if (!reg_not_null(reg1)) > > @@ -14896,27 +14917,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env, > > } > > > > is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32; > > - > > - if (BPF_SRC(insn->code) == BPF_K) { > > - pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32); > > - } else if (src_reg->type == SCALAR_VALUE && > > - is_jmp32 && tnum_is_const(tnum_subreg(src_reg->var_off))) { > > - pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32); > > - } else if (src_reg->type == SCALAR_VALUE && > > - !is_jmp32 && tnum_is_const(src_reg->var_off)) { > > - pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32); > > - } else if (dst_reg->type == SCALAR_VALUE && > > - is_jmp32 && tnum_is_const(tnum_subreg(dst_reg->var_off))) { > > - pred = is_branch_taken(src_reg, dst_reg, flip_opcode(opcode), is_jmp32); > > - } else if (dst_reg->type == SCALAR_VALUE && > > - !is_jmp32 && tnum_is_const(dst_reg->var_off)) { > > - pred = is_branch_taken(src_reg, dst_reg, flip_opcode(opcode), is_jmp32); > > - } else if (reg_is_pkt_pointer_any(dst_reg) && > > - reg_is_pkt_pointer_any(src_reg) && > > - !is_jmp32) { > > - pred = is_pkt_ptr_branch_taken(dst_reg, src_reg, opcode); > > - } > > - > > + pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32); > > if (pred >= 0) { > > /* If we get here with a dst_reg pointer type it is because > > * above is_branch_taken() special cased the 0 comparison.