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