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 8SEC("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; \ 15l0_%=: r0 += 1; \ 16 if r0 < 4 goto l0_%=; \ 17 exit; \ 18" ::: __clobber_all); 19} 20 21SEC("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; \ 28l0_%=: r0 += 3; \ 29 if r0 < 20 goto l0_%=; \ 30 exit; \ 31" ::: __clobber_all); 32} 33 34SEC("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_%=; \ 42l1_%=: r0 += 1; \ 43 if r0 < 4 goto l1_%=; \ 44l0_%=: exit; \ 45" : 46 : __imm(bpf_get_prandom_u32) 47 : __clobber_all); 48} 49 50SEC("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]; \ 57l0_%=: r0 += 1; \ 58 if r0 < 4 goto l0_%=; \ 59 exit; \ 60" : 61 : __imm(bpf_get_prandom_u32) 62 : __clobber_all); 63} 64 65SEC("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; \ 72l0_%=: r0 += 1; \ 73 if r0 != 4 goto l0_%=; \ 74 exit; \ 75" ::: __clobber_all); 76} 77 78SEC("socket") 79__description("bounded loop, start in the middle") 80__success 81__failure_unpriv __msg_unpriv("back-edge") 82__naked void loop_start_in_the_middle(void) 83{ 84 asm volatile (" \ 85 r0 = 0; \ 86 goto l0_%=; \ 87l1_%=: r0 += 1; \ 88l0_%=: if r0 < 4 goto l1_%=; \ 89 exit; \ 90" ::: __clobber_all); 91} 92 93SEC("xdp") 94__description("bounded loop containing a forward jump") 95__success __retval(4) 96__naked void loop_containing_a_forward_jump(void) 97{ 98 asm volatile (" \ 99 r0 = 0; \ 100l1_%=: r0 += 1; \ 101 if r0 == r0 goto l0_%=; \ 102l0_%=: if r0 < 4 goto l1_%=; \ 103 exit; \ 104" ::: __clobber_all); 105} 106 107SEC("tracepoint") 108__description("bounded loop that jumps out rather than in") 109__success 110__naked void jumps_out_rather_than_in(void) 111{ 112 asm volatile (" \ 113 r6 = 0; \ 114l1_%=: r6 += 1; \ 115 if r6 > 10000 goto l0_%=; \ 116 call %[bpf_get_prandom_u32]; \ 117 goto l1_%=; \ 118l0_%=: exit; \ 119" : 120 : __imm(bpf_get_prandom_u32) 121 : __clobber_all); 122} 123 124SEC("tracepoint") 125__description("infinite loop after a conditional jump") 126__failure __msg("program is too large") 127__naked void loop_after_a_conditional_jump(void) 128{ 129 asm volatile (" \ 130 r0 = 5; \ 131 if r0 < 4 goto l0_%=; \ 132l1_%=: r0 += 1; \ 133 goto l1_%=; \ 134l0_%=: exit; \ 135" ::: __clobber_all); 136} 137 138SEC("tracepoint") 139__description("bounded recursion") 140__failure 141/* verifier limitation in detecting max stack depth */ 142__msg("the call stack of 8 frames is too deep !") 143__naked void bounded_recursion(void) 144{ 145 asm volatile (" \ 146 r1 = 0; \ 147 call bounded_recursion__1; \ 148 exit; \ 149" ::: __clobber_all); 150} 151 152static __naked __noinline __attribute__((used)) 153void bounded_recursion__1(void) 154{ 155 asm volatile (" \ 156 r1 += 1; \ 157 r0 = r1; \ 158 if r1 < 4 goto l0_%=; \ 159 exit; \ 160l0_%=: call bounded_recursion__1; \ 161 exit; \ 162" ::: __clobber_all); 163} 164 165SEC("tracepoint") 166__description("infinite loop in two jumps") 167__failure __msg("loop detected") 168__naked void infinite_loop_in_two_jumps(void) 169{ 170 asm volatile (" \ 171 r0 = 0; \ 172l1_%=: goto l0_%=; \ 173l0_%=: if r0 < 4 goto l1_%=; \ 174 exit; \ 175" ::: __clobber_all); 176} 177 178SEC("tracepoint") 179__description("infinite loop: three-jump trick") 180__failure __msg("loop detected") 181__naked void infinite_loop_three_jump_trick(void) 182{ 183 asm volatile (" \ 184 r0 = 0; \ 185l2_%=: r0 += 1; \ 186 r0 &= 1; \ 187 if r0 < 2 goto l0_%=; \ 188 exit; \ 189l0_%=: r0 += 1; \ 190 r0 &= 1; \ 191 if r0 < 2 goto l1_%=; \ 192 exit; \ 193l1_%=: r0 += 1; \ 194 r0 &= 1; \ 195 if r0 < 2 goto l2_%=; \ 196 exit; \ 197" ::: __clobber_all); 198} 199 200SEC("xdp") 201__description("not-taken loop with back jump to 1st insn") 202__success __retval(123) 203__naked void back_jump_to_1st_insn_1(void) 204{ 205 asm volatile (" \ 206l0_%=: r0 = 123; \ 207 if r0 == 4 goto l0_%=; \ 208 exit; \ 209" ::: __clobber_all); 210} 211 212SEC("xdp") 213__description("taken loop with back jump to 1st insn") 214__success __retval(55) 215__naked void back_jump_to_1st_insn_2(void) 216{ 217 asm volatile (" \ 218 r1 = 10; \ 219 r2 = 0; \ 220 call back_jump_to_1st_insn_2__1; \ 221 exit; \ 222" ::: __clobber_all); 223} 224 225static __naked __noinline __attribute__((used)) 226void back_jump_to_1st_insn_2__1(void) 227{ 228 asm volatile (" \ 229l0_%=: r2 += r1; \ 230 r1 -= 1; \ 231 if r1 != 0 goto l0_%=; \ 232 r0 = r2; \ 233 exit; \ 234" ::: __clobber_all); 235} 236 237SEC("xdp") 238__description("taken loop with back jump to 1st insn, 2") 239__success __retval(55) 240__naked void jump_to_1st_insn_2(void) 241{ 242 asm volatile (" \ 243 r1 = 10; \ 244 r2 = 0; \ 245 call jump_to_1st_insn_2__1; \ 246 exit; \ 247" ::: __clobber_all); 248} 249 250static __naked __noinline __attribute__((used)) 251void jump_to_1st_insn_2__1(void) 252{ 253 asm volatile (" \ 254l0_%=: r2 += r1; \ 255 r1 -= 1; \ 256 if w1 != 0 goto l0_%=; \ 257 r0 = r2; \ 258 exit; \ 259" ::: __clobber_all); 260} 261 262SEC("xdp") 263__success 264__naked void not_an_inifinite_loop(void) 265{ 266 asm volatile (" \ 267 call %[bpf_get_prandom_u32]; \ 268 r0 &= 0xff; \ 269 *(u64 *)(r10 - 8) = r0; \ 270 r0 = 0; \ 271loop_%=: \ 272 r0 = *(u64 *)(r10 - 8); \ 273 if r0 > 10 goto exit_%=; \ 274 r0 += 1; \ 275 *(u64 *)(r10 - 8) = r0; \ 276 r0 = 0; \ 277 goto loop_%=; \ 278exit_%=: \ 279 r0 = 0; \ 280 exit; \ 281" : 282 : __imm(bpf_get_prandom_u32) 283 : __clobber_all); 284} 285 286char _license[] SEC("license") = "GPL"; 287