@@ -4410,8 +4410,10 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
44104410 * before it would be equally necessary to
44114411 * propagate it to dreg.
44124412 */
4413- bt_set_reg(bt, dreg);
4414- bt_set_reg(bt, sreg);
4413+ if (!hist || !(hist->flags & INSN_F_SRC_REG_STACK))
4414+ bt_set_reg(bt, sreg);
4415+ if (!hist || !(hist->flags & INSN_F_DST_REG_STACK))
4416+ bt_set_reg(bt, dreg);
44154417 } else if (BPF_SRC(insn->code) == BPF_K) {
44164418 /* dreg <cond> K
44174419 * Only dreg still needs precision before
@@ -16392,6 +16394,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
1639216394 struct bpf_reg_state *eq_branch_regs;
1639316395 struct linked_regs linked_regs = {};
1639416396 u8 opcode = BPF_OP(insn->code);
16397+ int insn_flags = 0;
1639516398 bool is_jmp32;
1639616399 int pred = -1;
1639716400 int err;
@@ -16450,6 +16453,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
1645016453 insn->src_reg);
1645116454 return -EACCES;
1645216455 }
16456+
16457+ if (src_reg->type == PTR_TO_STACK)
16458+ insn_flags |= INSN_F_SRC_REG_STACK;
1645316459 } else {
1645416460 if (insn->src_reg != BPF_REG_0) {
1645516461 verbose(env, "BPF_JMP/JMP32 uses reserved fields\n");
@@ -16461,6 +16467,14 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
1646116467 __mark_reg_known(src_reg, insn->imm);
1646216468 }
1646316469
16470+ if (dst_reg->type == PTR_TO_STACK)
16471+ insn_flags |= INSN_F_DST_REG_STACK;
16472+ if (insn_flags) {
16473+ err = push_insn_history(env, this_branch, insn_flags, 0);
16474+ if (err)
16475+ return err;
16476+ }
16477+
1646416478 is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
1646516479 pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32);
1646616480 if (pred >= 0) {
0 commit comments