Skip to content

Commit 223ffb6

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
selftests/bpf: add reproducer for spurious precision propagation through calls
Add a test for the scenario described in the previous commit: an iterator loop with two paths where one ties r2/r7 via shared scalar id and skips a call, while the other goes through the call. Precision marks from the linked registers get spuriously propagated to the call path via propagate_precision(), hitting "backtracking call unexpected regs" in backtrack_insn(). Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20260306-linked-regs-and-propagate-precision-v1-2-18e859be570d@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 2658a17 commit 223ffb6

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

tools/testing/selftests/bpf/progs/verifier_linked_scalars.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,68 @@ void alu32_negative_offset(void)
363363
__sink(path[0]);
364364
}
365365

366+
void dummy_calls(void)
367+
{
368+
bpf_iter_num_new(0, 0, 0);
369+
bpf_iter_num_next(0);
370+
bpf_iter_num_destroy(0);
371+
}
372+
373+
SEC("socket")
374+
__success
375+
__flag(BPF_F_TEST_STATE_FREQ)
376+
int spurious_precision_marks(void *ctx)
377+
{
378+
struct bpf_iter_num iter;
379+
380+
asm volatile(
381+
"r1 = %[iter];"
382+
"r2 = 0;"
383+
"r3 = 10;"
384+
"call %[bpf_iter_num_new];"
385+
"1:"
386+
"r1 = %[iter];"
387+
"call %[bpf_iter_num_next];"
388+
"if r0 == 0 goto 4f;"
389+
"r7 = *(u32 *)(r0 + 0);"
390+
"r8 = *(u32 *)(r0 + 0);"
391+
/* This jump can't be predicted and does not change r7 or r8 state. */
392+
"if r7 > r8 goto 2f;"
393+
/* Branch explored first ties r2 and r7 as having the same id. */
394+
"r2 = r7;"
395+
"goto 3f;"
396+
"2:"
397+
/* Branch explored second does not tie r2 and r7 but has a function call. */
398+
"call %[bpf_get_prandom_u32];"
399+
"3:"
400+
/*
401+
* A checkpoint.
402+
* When first branch is explored, this would inject linked registers
403+
* r2 and r7 into the jump history.
404+
* When second branch is explored, this would be a cache hit point,
405+
* triggering propagate_precision().
406+
*/
407+
"if r7 <= 42 goto +0;"
408+
/*
409+
* Mark r7 as precise using an if condition that is always true.
410+
* When reached via the second branch, this triggered a bug in the backtrack_insn()
411+
* because r2 (tied to r7) was propagated as precise to a call.
412+
*/
413+
"if r7 <= 0xffffFFFF goto +0;"
414+
"goto 1b;"
415+
"4:"
416+
"r1 = %[iter];"
417+
"call %[bpf_iter_num_destroy];"
418+
:
419+
: __imm_ptr(iter),
420+
__imm(bpf_iter_num_new),
421+
__imm(bpf_iter_num_next),
422+
__imm(bpf_iter_num_destroy),
423+
__imm(bpf_get_prandom_u32)
424+
: __clobber_common, "r7", "r8"
425+
);
426+
427+
return 0;
428+
}
429+
366430
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)