@@ -4410,8 +4410,10 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
4410
4410
* before it would be equally necessary to
4411
4411
* propagate it to dreg.
4412
4412
*/
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);
4415
4417
} else if (BPF_SRC(insn->code) == BPF_K) {
4416
4418
/* dreg <cond> K
4417
4419
* Only dreg still needs precision before
@@ -16392,6 +16394,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
16392
16394
struct bpf_reg_state *eq_branch_regs;
16393
16395
struct linked_regs linked_regs = {};
16394
16396
u8 opcode = BPF_OP(insn->code);
16397
+ int insn_flags = 0;
16395
16398
bool is_jmp32;
16396
16399
int pred = -1;
16397
16400
int err;
@@ -16450,6 +16453,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
16450
16453
insn->src_reg);
16451
16454
return -EACCES;
16452
16455
}
16456
+
16457
+ if (src_reg->type == PTR_TO_STACK)
16458
+ insn_flags |= INSN_F_SRC_REG_STACK;
16453
16459
} else {
16454
16460
if (insn->src_reg != BPF_REG_0) {
16455
16461
verbose(env, "BPF_JMP/JMP32 uses reserved fields\n");
@@ -16461,6 +16467,14 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
16461
16467
__mark_reg_known(src_reg, insn->imm);
16462
16468
}
16463
16469
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
+
16464
16478
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
16465
16479
pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32);
16466
16480
if (pred >= 0) {
0 commit comments