From: Alexei Starovoitov After 'r3 = r8; r3 += 4' the verifier knows that r3 == r8 + 4. The two registers have the same id, and r3 keeps the difference in reg->delta. When the prog compares one of them with a constant, sync_linked_regs() calculates the range of the other register from the difference of the two deltas. At a loop head scalar evolution widens a register: it replaces the register with its range over all iterations. Then the register is not linked to other registers. scratch_widened_reg_id() clears reg->id, but it does not clear reg->delta. A subsequent copy of the register gets the stale delta. Then the range of the copy is incorrect by this delta. r3 = r8 r3 += 4 ; R3=scalar(id=1+4) 1: ; r3 is widened: no id, delta is still 4 r4 = r3 ; id=2 and delta 4 in both r4 += 1 ; R4=scalar(id=2+1) if r3 > 10 goto 3f ; R3 <= 10, R4 = R3 + 1 - 4 <= 7 if r4 <= 7 goto 2f ... ; not verified, r4 is up to 11 here The verifier does not verify code that can run. Clear delta together with id. Fixes: 6ccf49f79327 ("bpf: Use SCEV to widen bounded loops") Signed-off-by: Alexei Starovoitov --- kernel/bpf/scev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c index fea77772ca96..b321bfee36c5 100644 --- a/kernel/bpf/scev.c +++ b/kernel/bpf/scev.c @@ -2390,6 +2390,7 @@ static void scratch_widened_reg_id(struct bpf_verifier_env *env, struct bpf_reg_ switch (base_type(reg->type)) { case SCALAR_VALUE: reg->id = 0; + reg->delta = 0; break; case PTR_TO_PACKET: case PTR_TO_PACKET_META: -- 2.55.0