bpf_do_misc_fixups() expands a backward may_goto to gotol when the patches queued between it and its target push its offset out of the 16-bit range. No test covers a backward may_goto whose expanded jump only goes out of the 16-bit range through the patches in between. Check that a may_goto jumping back over 8191 guarded divisions loads and is expanded to gotol. Signed-off-by: Qiliang Yuan --- .../selftests/bpf/progs/verifier_patch_list.c | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/verifier_patch_list.c b/tools/testing/selftests/bpf/progs/verifier_patch_list.c index 1370cdd5e5836..302e739caf83c 100644 --- a/tools/testing/selftests/bpf/progs/verifier_patch_list.c +++ b/tools/testing/selftests/bpf/progs/verifier_patch_list.c @@ -172,4 +172,39 @@ l0_%=: \ } #endif +/* + * may_goto jumps back by 8195 insns, by 32768 once each of the 8191 + * divisions is guarded by a patch of 4 insns. That still fits the 16 bits of + * may_goto, but not the jump it expands to, which has to become gotol. Once + * the budget runs out, may_goto jumps back with r6 set and the program exits. + */ +SEC("raw_tp") +__description("patch list: backward may_goto expanded to gotol") +__arch_x86_64 +__success +__xlated("...") +__xlated("{{[0-9]+}}: gotol pc-{{[0-9]+}}") +__naked void patch_list_may_goto_gotol(void) +{ + asm volatile (" \ + call %[bpf_get_prandom_u32]; \ + r1 = r0; \ + r6 = 0; \ + goto 0f; \ +1: r0 = 0; \ + exit; \ +0: if r6 != 0 goto 1b; \ + .rept 8191; \ + r0 /= r1; \ + .endr; \ + r2 = 0; \ + r6 = 1; \ + may_goto 0b; \ + r0 = 0; \ + exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + char _license[] SEC("license") = "GPL"; -- 2.43.0