1a6fc14dcSEduard Zingerman // SPDX-License-Identifier: GPL-2.0 2a6fc14dcSEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/loops1.c */ 3a6fc14dcSEduard Zingerman 4a6fc14dcSEduard Zingerman #include <linux/bpf.h> 5a6fc14dcSEduard Zingerman #include <bpf/bpf_helpers.h> 6a6fc14dcSEduard Zingerman #include "bpf_misc.h" 7a6fc14dcSEduard Zingerman 8a6fc14dcSEduard Zingerman SEC("xdp") 9a6fc14dcSEduard Zingerman __description("bounded loop, count to 4") 10a6fc14dcSEduard Zingerman __success __retval(4) bounded_loop_count_to_4(void)11a6fc14dcSEduard Zingerman__naked void bounded_loop_count_to_4(void) 12a6fc14dcSEduard Zingerman { 13a6fc14dcSEduard Zingerman asm volatile (" \ 14a6fc14dcSEduard Zingerman r0 = 0; \ 15a6fc14dcSEduard Zingerman l0_%=: r0 += 1; \ 16a6fc14dcSEduard Zingerman if r0 < 4 goto l0_%=; \ 17a6fc14dcSEduard Zingerman exit; \ 18a6fc14dcSEduard Zingerman " ::: __clobber_all); 19a6fc14dcSEduard Zingerman } 20a6fc14dcSEduard Zingerman 21a6fc14dcSEduard Zingerman SEC("tracepoint") 22a6fc14dcSEduard Zingerman __description("bounded loop, count to 20") 23a6fc14dcSEduard Zingerman __success bounded_loop_count_to_20(void)24a6fc14dcSEduard Zingerman__naked void bounded_loop_count_to_20(void) 25a6fc14dcSEduard Zingerman { 26a6fc14dcSEduard Zingerman asm volatile (" \ 27a6fc14dcSEduard Zingerman r0 = 0; \ 28a6fc14dcSEduard Zingerman l0_%=: r0 += 3; \ 29a6fc14dcSEduard Zingerman if r0 < 20 goto l0_%=; \ 30a6fc14dcSEduard Zingerman exit; \ 31a6fc14dcSEduard Zingerman " ::: __clobber_all); 32a6fc14dcSEduard Zingerman } 33a6fc14dcSEduard Zingerman 34a6fc14dcSEduard Zingerman SEC("tracepoint") 35a6fc14dcSEduard Zingerman __description("bounded loop, count from positive unknown to 4") 36a6fc14dcSEduard Zingerman __success from_positive_unknown_to_4(void)37a6fc14dcSEduard Zingerman__naked void from_positive_unknown_to_4(void) 38a6fc14dcSEduard Zingerman { 39a6fc14dcSEduard Zingerman asm volatile (" \ 40a6fc14dcSEduard Zingerman call %[bpf_get_prandom_u32]; \ 41a6fc14dcSEduard Zingerman if r0 s< 0 goto l0_%=; \ 42a6fc14dcSEduard Zingerman l1_%=: r0 += 1; \ 43a6fc14dcSEduard Zingerman if r0 < 4 goto l1_%=; \ 44a6fc14dcSEduard Zingerman l0_%=: exit; \ 45a6fc14dcSEduard Zingerman " : 46a6fc14dcSEduard Zingerman : __imm(bpf_get_prandom_u32) 47a6fc14dcSEduard Zingerman : __clobber_all); 48a6fc14dcSEduard Zingerman } 49a6fc14dcSEduard Zingerman 50a6fc14dcSEduard Zingerman SEC("tracepoint") 51a6fc14dcSEduard Zingerman __description("bounded loop, count from totally unknown to 4") 52a6fc14dcSEduard Zingerman __success from_totally_unknown_to_4(void)53a6fc14dcSEduard Zingerman__naked void from_totally_unknown_to_4(void) 54a6fc14dcSEduard Zingerman { 55a6fc14dcSEduard Zingerman asm volatile (" \ 56a6fc14dcSEduard Zingerman call %[bpf_get_prandom_u32]; \ 57a6fc14dcSEduard Zingerman l0_%=: r0 += 1; \ 58a6fc14dcSEduard Zingerman if r0 < 4 goto l0_%=; \ 59a6fc14dcSEduard Zingerman exit; \ 60a6fc14dcSEduard Zingerman " : 61a6fc14dcSEduard Zingerman : __imm(bpf_get_prandom_u32) 62a6fc14dcSEduard Zingerman : __clobber_all); 63a6fc14dcSEduard Zingerman } 64a6fc14dcSEduard Zingerman 65a6fc14dcSEduard Zingerman SEC("tracepoint") 66a6fc14dcSEduard Zingerman __description("bounded loop, count to 4 with equality") 67a6fc14dcSEduard Zingerman __success count_to_4_with_equality(void)68a6fc14dcSEduard Zingerman__naked void count_to_4_with_equality(void) 69a6fc14dcSEduard Zingerman { 70a6fc14dcSEduard Zingerman asm volatile (" \ 71a6fc14dcSEduard Zingerman r0 = 0; \ 72a6fc14dcSEduard Zingerman l0_%=: r0 += 1; \ 73a6fc14dcSEduard Zingerman if r0 != 4 goto l0_%=; \ 74a6fc14dcSEduard Zingerman exit; \ 75a6fc14dcSEduard Zingerman " ::: __clobber_all); 76a6fc14dcSEduard Zingerman } 77a6fc14dcSEduard Zingerman 78*9549f53aSAndrii Nakryiko SEC("socket") 79a6fc14dcSEduard Zingerman __description("bounded loop, start in the middle") 80*9549f53aSAndrii Nakryiko __success 81*9549f53aSAndrii Nakryiko __failure_unpriv __msg_unpriv("back-edge") loop_start_in_the_middle(void)82a6fc14dcSEduard Zingerman__naked void loop_start_in_the_middle(void) 83a6fc14dcSEduard Zingerman { 84a6fc14dcSEduard Zingerman asm volatile (" \ 85a6fc14dcSEduard Zingerman r0 = 0; \ 86a6fc14dcSEduard Zingerman goto l0_%=; \ 87a6fc14dcSEduard Zingerman l1_%=: r0 += 1; \ 88a6fc14dcSEduard Zingerman l0_%=: if r0 < 4 goto l1_%=; \ 89a6fc14dcSEduard Zingerman exit; \ 90a6fc14dcSEduard Zingerman " ::: __clobber_all); 91a6fc14dcSEduard Zingerman } 92a6fc14dcSEduard Zingerman 93a6fc14dcSEduard Zingerman SEC("xdp") 94a6fc14dcSEduard Zingerman __description("bounded loop containing a forward jump") 95a6fc14dcSEduard Zingerman __success __retval(4) loop_containing_a_forward_jump(void)96a6fc14dcSEduard Zingerman__naked void loop_containing_a_forward_jump(void) 97a6fc14dcSEduard Zingerman { 98a6fc14dcSEduard Zingerman asm volatile (" \ 99a6fc14dcSEduard Zingerman r0 = 0; \ 100a6fc14dcSEduard Zingerman l1_%=: r0 += 1; \ 101a6fc14dcSEduard Zingerman if r0 == r0 goto l0_%=; \ 102a6fc14dcSEduard Zingerman l0_%=: if r0 < 4 goto l1_%=; \ 103a6fc14dcSEduard Zingerman exit; \ 104a6fc14dcSEduard Zingerman " ::: __clobber_all); 105a6fc14dcSEduard Zingerman } 106a6fc14dcSEduard Zingerman 107a6fc14dcSEduard Zingerman SEC("tracepoint") 108a6fc14dcSEduard Zingerman __description("bounded loop that jumps out rather than in") 109a6fc14dcSEduard Zingerman __success jumps_out_rather_than_in(void)110a6fc14dcSEduard Zingerman__naked void jumps_out_rather_than_in(void) 111a6fc14dcSEduard Zingerman { 112a6fc14dcSEduard Zingerman asm volatile (" \ 113a6fc14dcSEduard Zingerman r6 = 0; \ 114a6fc14dcSEduard Zingerman l1_%=: r6 += 1; \ 115a6fc14dcSEduard Zingerman if r6 > 10000 goto l0_%=; \ 116a6fc14dcSEduard Zingerman call %[bpf_get_prandom_u32]; \ 117a6fc14dcSEduard Zingerman goto l1_%=; \ 118a6fc14dcSEduard Zingerman l0_%=: exit; \ 119a6fc14dcSEduard Zingerman " : 120a6fc14dcSEduard Zingerman : __imm(bpf_get_prandom_u32) 121a6fc14dcSEduard Zingerman : __clobber_all); 122a6fc14dcSEduard Zingerman } 123a6fc14dcSEduard Zingerman 124a6fc14dcSEduard Zingerman SEC("tracepoint") 125a6fc14dcSEduard Zingerman __description("infinite loop after a conditional jump") 126a6fc14dcSEduard Zingerman __failure __msg("program is too large") loop_after_a_conditional_jump(void)127a6fc14dcSEduard Zingerman__naked void loop_after_a_conditional_jump(void) 128a6fc14dcSEduard Zingerman { 129a6fc14dcSEduard Zingerman asm volatile (" \ 130a6fc14dcSEduard Zingerman r0 = 5; \ 131a6fc14dcSEduard Zingerman if r0 < 4 goto l0_%=; \ 132a6fc14dcSEduard Zingerman l1_%=: r0 += 1; \ 133a6fc14dcSEduard Zingerman goto l1_%=; \ 134a6fc14dcSEduard Zingerman l0_%=: exit; \ 135a6fc14dcSEduard Zingerman " ::: __clobber_all); 136a6fc14dcSEduard Zingerman } 137a6fc14dcSEduard Zingerman 138a6fc14dcSEduard Zingerman SEC("tracepoint") 139a6fc14dcSEduard Zingerman __description("bounded recursion") 140*9549f53aSAndrii Nakryiko __failure 141*9549f53aSAndrii Nakryiko /* verifier limitation in detecting max stack depth */ 142*9549f53aSAndrii Nakryiko __msg("the call stack of 8 frames is too deep !") bounded_recursion(void)143a6fc14dcSEduard Zingerman__naked void bounded_recursion(void) 144a6fc14dcSEduard Zingerman { 145a6fc14dcSEduard Zingerman asm volatile (" \ 146a6fc14dcSEduard Zingerman r1 = 0; \ 147a6fc14dcSEduard Zingerman call bounded_recursion__1; \ 148a6fc14dcSEduard Zingerman exit; \ 149a6fc14dcSEduard Zingerman " ::: __clobber_all); 150a6fc14dcSEduard Zingerman } 151a6fc14dcSEduard Zingerman 152a6fc14dcSEduard Zingerman static __naked __noinline __attribute__((used)) bounded_recursion__1(void)153a6fc14dcSEduard Zingermanvoid bounded_recursion__1(void) 154a6fc14dcSEduard Zingerman { 155a6fc14dcSEduard Zingerman asm volatile (" \ 156a6fc14dcSEduard Zingerman r1 += 1; \ 157a6fc14dcSEduard Zingerman r0 = r1; \ 158a6fc14dcSEduard Zingerman if r1 < 4 goto l0_%=; \ 159a6fc14dcSEduard Zingerman exit; \ 160a6fc14dcSEduard Zingerman l0_%=: call bounded_recursion__1; \ 161a6fc14dcSEduard Zingerman exit; \ 162a6fc14dcSEduard Zingerman " ::: __clobber_all); 163a6fc14dcSEduard Zingerman } 164a6fc14dcSEduard Zingerman 165a6fc14dcSEduard Zingerman SEC("tracepoint") 166a6fc14dcSEduard Zingerman __description("infinite loop in two jumps") 167a6fc14dcSEduard Zingerman __failure __msg("loop detected") infinite_loop_in_two_jumps(void)168a6fc14dcSEduard Zingerman__naked void infinite_loop_in_two_jumps(void) 169a6fc14dcSEduard Zingerman { 170a6fc14dcSEduard Zingerman asm volatile (" \ 171a6fc14dcSEduard Zingerman r0 = 0; \ 172a6fc14dcSEduard Zingerman l1_%=: goto l0_%=; \ 173a6fc14dcSEduard Zingerman l0_%=: if r0 < 4 goto l1_%=; \ 174a6fc14dcSEduard Zingerman exit; \ 175a6fc14dcSEduard Zingerman " ::: __clobber_all); 176a6fc14dcSEduard Zingerman } 177a6fc14dcSEduard Zingerman 178a6fc14dcSEduard Zingerman SEC("tracepoint") 179a6fc14dcSEduard Zingerman __description("infinite loop: three-jump trick") 180a6fc14dcSEduard Zingerman __failure __msg("loop detected") infinite_loop_three_jump_trick(void)181a6fc14dcSEduard Zingerman__naked void infinite_loop_three_jump_trick(void) 182a6fc14dcSEduard Zingerman { 183a6fc14dcSEduard Zingerman asm volatile (" \ 184a6fc14dcSEduard Zingerman r0 = 0; \ 185a6fc14dcSEduard Zingerman l2_%=: r0 += 1; \ 186a6fc14dcSEduard Zingerman r0 &= 1; \ 187a6fc14dcSEduard Zingerman if r0 < 2 goto l0_%=; \ 188a6fc14dcSEduard Zingerman exit; \ 189a6fc14dcSEduard Zingerman l0_%=: r0 += 1; \ 190a6fc14dcSEduard Zingerman r0 &= 1; \ 191a6fc14dcSEduard Zingerman if r0 < 2 goto l1_%=; \ 192a6fc14dcSEduard Zingerman exit; \ 193a6fc14dcSEduard Zingerman l1_%=: r0 += 1; \ 194a6fc14dcSEduard Zingerman r0 &= 1; \ 195a6fc14dcSEduard Zingerman if r0 < 2 goto l2_%=; \ 196a6fc14dcSEduard Zingerman exit; \ 197a6fc14dcSEduard Zingerman " ::: __clobber_all); 198a6fc14dcSEduard Zingerman } 199a6fc14dcSEduard Zingerman 200a6fc14dcSEduard Zingerman SEC("xdp") 201a6fc14dcSEduard Zingerman __description("not-taken loop with back jump to 1st insn") 202a6fc14dcSEduard Zingerman __success __retval(123) back_jump_to_1st_insn_1(void)203a6fc14dcSEduard Zingerman__naked void back_jump_to_1st_insn_1(void) 204a6fc14dcSEduard Zingerman { 205a6fc14dcSEduard Zingerman asm volatile (" \ 206a6fc14dcSEduard Zingerman l0_%=: r0 = 123; \ 207a6fc14dcSEduard Zingerman if r0 == 4 goto l0_%=; \ 208a6fc14dcSEduard Zingerman exit; \ 209a6fc14dcSEduard Zingerman " ::: __clobber_all); 210a6fc14dcSEduard Zingerman } 211a6fc14dcSEduard Zingerman 212a6fc14dcSEduard Zingerman SEC("xdp") 213a6fc14dcSEduard Zingerman __description("taken loop with back jump to 1st insn") 214a6fc14dcSEduard Zingerman __success __retval(55) back_jump_to_1st_insn_2(void)215a6fc14dcSEduard Zingerman__naked void back_jump_to_1st_insn_2(void) 216a6fc14dcSEduard Zingerman { 217a6fc14dcSEduard Zingerman asm volatile (" \ 218a6fc14dcSEduard Zingerman r1 = 10; \ 219a6fc14dcSEduard Zingerman r2 = 0; \ 220a6fc14dcSEduard Zingerman call back_jump_to_1st_insn_2__1; \ 221a6fc14dcSEduard Zingerman exit; \ 222a6fc14dcSEduard Zingerman " ::: __clobber_all); 223a6fc14dcSEduard Zingerman } 224a6fc14dcSEduard Zingerman 225a6fc14dcSEduard Zingerman static __naked __noinline __attribute__((used)) back_jump_to_1st_insn_2__1(void)226a6fc14dcSEduard Zingermanvoid back_jump_to_1st_insn_2__1(void) 227a6fc14dcSEduard Zingerman { 228a6fc14dcSEduard Zingerman asm volatile (" \ 229a6fc14dcSEduard Zingerman l0_%=: r2 += r1; \ 230a6fc14dcSEduard Zingerman r1 -= 1; \ 231a6fc14dcSEduard Zingerman if r1 != 0 goto l0_%=; \ 232a6fc14dcSEduard Zingerman r0 = r2; \ 233a6fc14dcSEduard Zingerman exit; \ 234a6fc14dcSEduard Zingerman " ::: __clobber_all); 235a6fc14dcSEduard Zingerman } 236a6fc14dcSEduard Zingerman 237a6fc14dcSEduard Zingerman SEC("xdp") 238a6fc14dcSEduard Zingerman __description("taken loop with back jump to 1st insn, 2") 239a6fc14dcSEduard Zingerman __success __retval(55) jump_to_1st_insn_2(void)240a6fc14dcSEduard Zingerman__naked void jump_to_1st_insn_2(void) 241a6fc14dcSEduard Zingerman { 242a6fc14dcSEduard Zingerman asm volatile (" \ 243a6fc14dcSEduard Zingerman r1 = 10; \ 244a6fc14dcSEduard Zingerman r2 = 0; \ 245a6fc14dcSEduard Zingerman call jump_to_1st_insn_2__1; \ 246a6fc14dcSEduard Zingerman exit; \ 247a6fc14dcSEduard Zingerman " ::: __clobber_all); 248a6fc14dcSEduard Zingerman } 249a6fc14dcSEduard Zingerman 250a6fc14dcSEduard Zingerman static __naked __noinline __attribute__((used)) jump_to_1st_insn_2__1(void)251a6fc14dcSEduard Zingermanvoid jump_to_1st_insn_2__1(void) 252a6fc14dcSEduard Zingerman { 253a6fc14dcSEduard Zingerman asm volatile (" \ 254a6fc14dcSEduard Zingerman l0_%=: r2 += r1; \ 255a6fc14dcSEduard Zingerman r1 -= 1; \ 256a6fc14dcSEduard Zingerman if w1 != 0 goto l0_%=; \ 257a6fc14dcSEduard Zingerman r0 = r2; \ 258a6fc14dcSEduard Zingerman exit; \ 259a6fc14dcSEduard Zingerman " ::: __clobber_all); 260a6fc14dcSEduard Zingerman } 261a6fc14dcSEduard Zingerman 262a6fc14dcSEduard Zingerman char _license[] SEC("license") = "GPL"; 263