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

selftests/bpf: A pro/epilogue test when the main prog jumps back to the 1st insn

This patch adds a pro/epilogue test when the main prog has a goto insn
that goes back to the very first instruction of the prog. It is
to test the correctness of the adjust_jmp_off(prog, 0, delta)
after the verifier has applied the prologue and/or epilogue patch.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20240829210833.388152-9-martin.lau@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Martin KaFai Lau and committed by
Alexei Starovoitov
42fdbbde b191b0fd

+151
+2
tools/testing/selftests/bpf/prog_tests/pro_epilogue.c
··· 4 4 #include <test_progs.h> 5 5 #include "pro_epilogue.skel.h" 6 6 #include "epilogue_tailcall.skel.h" 7 + #include "pro_epilogue_goto_start.skel.h" 7 8 8 9 struct st_ops_args { 9 10 __u64 a; ··· 52 51 void test_pro_epilogue(void) 53 52 { 54 53 RUN_TESTS(pro_epilogue); 54 + RUN_TESTS(pro_epilogue_goto_start); 55 55 if (test__start_subtest("tailcall")) 56 56 test_tailcall(); 57 57 }
+149
tools/testing/selftests/bpf/progs/pro_epilogue_goto_start.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <vmlinux.h> 5 + #include <bpf/bpf_tracing.h> 6 + #include "bpf_misc.h" 7 + #include "../bpf_testmod/bpf_testmod.h" 8 + #include "../bpf_testmod/bpf_testmod_kfunc.h" 9 + 10 + char _license[] SEC("license") = "GPL"; 11 + 12 + __success 13 + /* prologue */ 14 + __xlated("0: r6 = *(u64 *)(r1 +0)") 15 + __xlated("1: r7 = *(u64 *)(r6 +0)") 16 + __xlated("2: r7 += 1000") 17 + __xlated("3: *(u64 *)(r6 +0) = r7") 18 + /* main prog */ 19 + __xlated("4: if r1 == 0x0 goto pc+5") 20 + __xlated("5: if r1 == 0x1 goto pc+2") 21 + __xlated("6: r1 = 1") 22 + __xlated("7: goto pc-3") 23 + __xlated("8: r1 = 0") 24 + __xlated("9: goto pc-6") 25 + __xlated("10: r0 = 0") 26 + __xlated("11: exit") 27 + SEC("struct_ops/test_prologue_goto_start") 28 + __naked int test_prologue_goto_start(void) 29 + { 30 + asm volatile ( 31 + "if r1 == 0 goto +5;" 32 + "if r1 == 1 goto +2;" 33 + "r1 = 1;" 34 + "goto -3;" 35 + "r1 = 0;" 36 + "goto -6;" 37 + "r0 = 0;" 38 + "exit;" 39 + ::: __clobber_all); 40 + } 41 + 42 + __success 43 + /* save __u64 *ctx to stack */ 44 + __xlated("0: *(u64 *)(r10 -8) = r1") 45 + /* main prog */ 46 + __xlated("1: if r1 == 0x0 goto pc+5") 47 + __xlated("2: if r1 == 0x1 goto pc+2") 48 + __xlated("3: r1 = 1") 49 + __xlated("4: goto pc-3") 50 + __xlated("5: r1 = 0") 51 + __xlated("6: goto pc-6") 52 + __xlated("7: r0 = 0") 53 + /* epilogue */ 54 + __xlated("8: r1 = *(u64 *)(r10 -8)") 55 + __xlated("9: r1 = *(u64 *)(r1 +0)") 56 + __xlated("10: r6 = *(u64 *)(r1 +0)") 57 + __xlated("11: r6 += 10000") 58 + __xlated("12: *(u64 *)(r1 +0) = r6") 59 + __xlated("13: r0 = r6") 60 + __xlated("14: r0 *= 2") 61 + __xlated("15: exit") 62 + SEC("struct_ops/test_epilogue_goto_start") 63 + __naked int test_epilogue_goto_start(void) 64 + { 65 + asm volatile ( 66 + "if r1 == 0 goto +5;" 67 + "if r1 == 1 goto +2;" 68 + "r1 = 1;" 69 + "goto -3;" 70 + "r1 = 0;" 71 + "goto -6;" 72 + "r0 = 0;" 73 + "exit;" 74 + ::: __clobber_all); 75 + } 76 + 77 + __success 78 + /* prologue */ 79 + __xlated("0: r6 = *(u64 *)(r1 +0)") 80 + __xlated("1: r7 = *(u64 *)(r6 +0)") 81 + __xlated("2: r7 += 1000") 82 + __xlated("3: *(u64 *)(r6 +0) = r7") 83 + /* save __u64 *ctx to stack */ 84 + __xlated("4: *(u64 *)(r10 -8) = r1") 85 + /* main prog */ 86 + __xlated("5: if r1 == 0x0 goto pc+5") 87 + __xlated("6: if r1 == 0x1 goto pc+2") 88 + __xlated("7: r1 = 1") 89 + __xlated("8: goto pc-3") 90 + __xlated("9: r1 = 0") 91 + __xlated("10: goto pc-6") 92 + __xlated("11: r0 = 0") 93 + /* epilogue */ 94 + __xlated("12: r1 = *(u64 *)(r10 -8)") 95 + __xlated("13: r1 = *(u64 *)(r1 +0)") 96 + __xlated("14: r6 = *(u64 *)(r1 +0)") 97 + __xlated("15: r6 += 10000") 98 + __xlated("16: *(u64 *)(r1 +0) = r6") 99 + __xlated("17: r0 = r6") 100 + __xlated("18: r0 *= 2") 101 + __xlated("19: exit") 102 + SEC("struct_ops/test_pro_epilogue_goto_start") 103 + __naked int test_pro_epilogue_goto_start(void) 104 + { 105 + asm volatile ( 106 + "if r1 == 0 goto +5;" 107 + "if r1 == 1 goto +2;" 108 + "r1 = 1;" 109 + "goto -3;" 110 + "r1 = 0;" 111 + "goto -6;" 112 + "r0 = 0;" 113 + "exit;" 114 + ::: __clobber_all); 115 + } 116 + 117 + SEC(".struct_ops.link") 118 + struct bpf_testmod_st_ops epilogue_goto_start = { 119 + .test_prologue = (void *)test_prologue_goto_start, 120 + .test_epilogue = (void *)test_epilogue_goto_start, 121 + .test_pro_epilogue = (void *)test_pro_epilogue_goto_start, 122 + }; 123 + 124 + SEC("syscall") 125 + __retval(0) 126 + int syscall_prologue_goto_start(void *ctx) 127 + { 128 + struct st_ops_args args = {}; 129 + 130 + return bpf_kfunc_st_ops_test_prologue(&args); 131 + } 132 + 133 + SEC("syscall") 134 + __retval(20000) /* (EPILOGUE_A [10000]) * 2 */ 135 + int syscall_epilogue_goto_start(void *ctx) 136 + { 137 + struct st_ops_args args = {}; 138 + 139 + return bpf_kfunc_st_ops_test_epilogue(&args); 140 + } 141 + 142 + SEC("syscall") 143 + __retval(22000) /* (PROLOGUE_A [1000] + EPILOGUE_A [10000]) * 2 */ 144 + int syscall_pro_epilogue_goto_start(void *ctx) 145 + { 146 + struct st_ops_args args = {}; 147 + 148 + return bpf_kfunc_st_ops_test_pro_epilogue(&args); 149 + }