Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: add edge case backtracking logic test

Add a dedicated selftests to try to set up conditions to have a state
with same first and last instruction index, but it actually is a loop
3->4->1->2->3. This confuses mark_chain_precision() if verifier doesn't
take into account jump history.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20231110002638.4168352-4-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
62ccdb11 4bb7ea94

+40
+40
tools/testing/selftests/bpf/progs/verifier_precision.c
··· 91 91 } 92 92 93 93 #endif /* v4 instruction */ 94 + 95 + SEC("?raw_tp") 96 + __success __log_level(2) 97 + /* 98 + * Without the bug fix there will be no history between "last_idx 3 first_idx 3" 99 + * and "parent state regs=" lines. "R0_w=6" parts are here to help anchor 100 + * expected log messages to the one specific mark_chain_precision operation. 101 + * 102 + * This is quite fragile: if verifier checkpointing heuristic changes, this 103 + * might need adjusting. 104 + */ 105 + __msg("2: (07) r0 += 1 ; R0_w=6") 106 + __msg("3: (35) if r0 >= 0xa goto pc+1") 107 + __msg("mark_precise: frame0: last_idx 3 first_idx 3 subseq_idx -1") 108 + __msg("mark_precise: frame0: regs=r0 stack= before 2: (07) r0 += 1") 109 + __msg("mark_precise: frame0: regs=r0 stack= before 1: (07) r0 += 1") 110 + __msg("mark_precise: frame0: regs=r0 stack= before 4: (05) goto pc-4") 111 + __msg("mark_precise: frame0: regs=r0 stack= before 3: (35) if r0 >= 0xa goto pc+1") 112 + __msg("mark_precise: frame0: parent state regs= stack=: R0_rw=P4") 113 + __msg("3: R0_w=6") 114 + __naked int state_loop_first_last_equal(void) 115 + { 116 + asm volatile ( 117 + "r0 = 0;" 118 + "l0_%=:" 119 + "r0 += 1;" 120 + "r0 += 1;" 121 + /* every few iterations we'll have a checkpoint here with 122 + * first_idx == last_idx, potentially confusing precision 123 + * backtracking logic 124 + */ 125 + "if r0 >= 10 goto l1_%=;" /* checkpoint + mark_precise */ 126 + "goto l0_%=;" 127 + "l1_%=:" 128 + "exit;" 129 + ::: __clobber_common 130 + ); 131 + } 132 + 133 + char _license[] SEC("license") = "GPL";