162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Converted from tools/testing/selftests/bpf/verifier/loops1.c */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/bpf.h> 562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 662306a36Sopenharmony_ci#include "bpf_misc.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciSEC("xdp") 962306a36Sopenharmony_ci__description("bounded loop, count to 4") 1062306a36Sopenharmony_ci__success __retval(4) 1162306a36Sopenharmony_ci__naked void bounded_loop_count_to_4(void) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci asm volatile (" \ 1462306a36Sopenharmony_ci r0 = 0; \ 1562306a36Sopenharmony_cil0_%=: r0 += 1; \ 1662306a36Sopenharmony_ci if r0 < 4 goto l0_%=; \ 1762306a36Sopenharmony_ci exit; \ 1862306a36Sopenharmony_ci" ::: __clobber_all); 1962306a36Sopenharmony_ci} 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciSEC("tracepoint") 2262306a36Sopenharmony_ci__description("bounded loop, count to 20") 2362306a36Sopenharmony_ci__success 2462306a36Sopenharmony_ci__naked void bounded_loop_count_to_20(void) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci asm volatile (" \ 2762306a36Sopenharmony_ci r0 = 0; \ 2862306a36Sopenharmony_cil0_%=: r0 += 3; \ 2962306a36Sopenharmony_ci if r0 < 20 goto l0_%=; \ 3062306a36Sopenharmony_ci exit; \ 3162306a36Sopenharmony_ci" ::: __clobber_all); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciSEC("tracepoint") 3562306a36Sopenharmony_ci__description("bounded loop, count from positive unknown to 4") 3662306a36Sopenharmony_ci__success 3762306a36Sopenharmony_ci__naked void from_positive_unknown_to_4(void) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci asm volatile (" \ 4062306a36Sopenharmony_ci call %[bpf_get_prandom_u32]; \ 4162306a36Sopenharmony_ci if r0 s< 0 goto l0_%=; \ 4262306a36Sopenharmony_cil1_%=: r0 += 1; \ 4362306a36Sopenharmony_ci if r0 < 4 goto l1_%=; \ 4462306a36Sopenharmony_cil0_%=: exit; \ 4562306a36Sopenharmony_ci" : 4662306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32) 4762306a36Sopenharmony_ci : __clobber_all); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciSEC("tracepoint") 5162306a36Sopenharmony_ci__description("bounded loop, count from totally unknown to 4") 5262306a36Sopenharmony_ci__success 5362306a36Sopenharmony_ci__naked void from_totally_unknown_to_4(void) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci asm volatile (" \ 5662306a36Sopenharmony_ci call %[bpf_get_prandom_u32]; \ 5762306a36Sopenharmony_cil0_%=: r0 += 1; \ 5862306a36Sopenharmony_ci if r0 < 4 goto l0_%=; \ 5962306a36Sopenharmony_ci exit; \ 6062306a36Sopenharmony_ci" : 6162306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32) 6262306a36Sopenharmony_ci : __clobber_all); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciSEC("tracepoint") 6662306a36Sopenharmony_ci__description("bounded loop, count to 4 with equality") 6762306a36Sopenharmony_ci__success 6862306a36Sopenharmony_ci__naked void count_to_4_with_equality(void) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci asm volatile (" \ 7162306a36Sopenharmony_ci r0 = 0; \ 7262306a36Sopenharmony_cil0_%=: r0 += 1; \ 7362306a36Sopenharmony_ci if r0 != 4 goto l0_%=; \ 7462306a36Sopenharmony_ci exit; \ 7562306a36Sopenharmony_ci" ::: __clobber_all); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciSEC("socket") 7962306a36Sopenharmony_ci__description("bounded loop, start in the middle") 8062306a36Sopenharmony_ci__success 8162306a36Sopenharmony_ci__failure_unpriv __msg_unpriv("back-edge") 8262306a36Sopenharmony_ci__naked void loop_start_in_the_middle(void) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci asm volatile (" \ 8562306a36Sopenharmony_ci r0 = 0; \ 8662306a36Sopenharmony_ci goto l0_%=; \ 8762306a36Sopenharmony_cil1_%=: r0 += 1; \ 8862306a36Sopenharmony_cil0_%=: if r0 < 4 goto l1_%=; \ 8962306a36Sopenharmony_ci exit; \ 9062306a36Sopenharmony_ci" ::: __clobber_all); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciSEC("xdp") 9462306a36Sopenharmony_ci__description("bounded loop containing a forward jump") 9562306a36Sopenharmony_ci__success __retval(4) 9662306a36Sopenharmony_ci__naked void loop_containing_a_forward_jump(void) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci asm volatile (" \ 9962306a36Sopenharmony_ci r0 = 0; \ 10062306a36Sopenharmony_cil1_%=: r0 += 1; \ 10162306a36Sopenharmony_ci if r0 == r0 goto l0_%=; \ 10262306a36Sopenharmony_cil0_%=: if r0 < 4 goto l1_%=; \ 10362306a36Sopenharmony_ci exit; \ 10462306a36Sopenharmony_ci" ::: __clobber_all); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciSEC("tracepoint") 10862306a36Sopenharmony_ci__description("bounded loop that jumps out rather than in") 10962306a36Sopenharmony_ci__success 11062306a36Sopenharmony_ci__naked void jumps_out_rather_than_in(void) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci asm volatile (" \ 11362306a36Sopenharmony_ci r6 = 0; \ 11462306a36Sopenharmony_cil1_%=: r6 += 1; \ 11562306a36Sopenharmony_ci if r6 > 10000 goto l0_%=; \ 11662306a36Sopenharmony_ci call %[bpf_get_prandom_u32]; \ 11762306a36Sopenharmony_ci goto l1_%=; \ 11862306a36Sopenharmony_cil0_%=: exit; \ 11962306a36Sopenharmony_ci" : 12062306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32) 12162306a36Sopenharmony_ci : __clobber_all); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciSEC("tracepoint") 12562306a36Sopenharmony_ci__description("infinite loop after a conditional jump") 12662306a36Sopenharmony_ci__failure __msg("program is too large") 12762306a36Sopenharmony_ci__naked void loop_after_a_conditional_jump(void) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci asm volatile (" \ 13062306a36Sopenharmony_ci r0 = 5; \ 13162306a36Sopenharmony_ci if r0 < 4 goto l0_%=; \ 13262306a36Sopenharmony_cil1_%=: r0 += 1; \ 13362306a36Sopenharmony_ci goto l1_%=; \ 13462306a36Sopenharmony_cil0_%=: exit; \ 13562306a36Sopenharmony_ci" ::: __clobber_all); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciSEC("tracepoint") 13962306a36Sopenharmony_ci__description("bounded recursion") 14062306a36Sopenharmony_ci__failure 14162306a36Sopenharmony_ci/* verifier limitation in detecting max stack depth */ 14262306a36Sopenharmony_ci__msg("the call stack of 8 frames is too deep !") 14362306a36Sopenharmony_ci__naked void bounded_recursion(void) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci asm volatile (" \ 14662306a36Sopenharmony_ci r1 = 0; \ 14762306a36Sopenharmony_ci call bounded_recursion__1; \ 14862306a36Sopenharmony_ci exit; \ 14962306a36Sopenharmony_ci" ::: __clobber_all); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic __naked __noinline __attribute__((used)) 15362306a36Sopenharmony_civoid bounded_recursion__1(void) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci asm volatile (" \ 15662306a36Sopenharmony_ci r1 += 1; \ 15762306a36Sopenharmony_ci r0 = r1; \ 15862306a36Sopenharmony_ci if r1 < 4 goto l0_%=; \ 15962306a36Sopenharmony_ci exit; \ 16062306a36Sopenharmony_cil0_%=: call bounded_recursion__1; \ 16162306a36Sopenharmony_ci exit; \ 16262306a36Sopenharmony_ci" ::: __clobber_all); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciSEC("tracepoint") 16662306a36Sopenharmony_ci__description("infinite loop in two jumps") 16762306a36Sopenharmony_ci__failure __msg("loop detected") 16862306a36Sopenharmony_ci__naked void infinite_loop_in_two_jumps(void) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci asm volatile (" \ 17162306a36Sopenharmony_ci r0 = 0; \ 17262306a36Sopenharmony_cil1_%=: goto l0_%=; \ 17362306a36Sopenharmony_cil0_%=: if r0 < 4 goto l1_%=; \ 17462306a36Sopenharmony_ci exit; \ 17562306a36Sopenharmony_ci" ::: __clobber_all); 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciSEC("tracepoint") 17962306a36Sopenharmony_ci__description("infinite loop: three-jump trick") 18062306a36Sopenharmony_ci__failure __msg("loop detected") 18162306a36Sopenharmony_ci__naked void infinite_loop_three_jump_trick(void) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci asm volatile (" \ 18462306a36Sopenharmony_ci r0 = 0; \ 18562306a36Sopenharmony_cil2_%=: r0 += 1; \ 18662306a36Sopenharmony_ci r0 &= 1; \ 18762306a36Sopenharmony_ci if r0 < 2 goto l0_%=; \ 18862306a36Sopenharmony_ci exit; \ 18962306a36Sopenharmony_cil0_%=: r0 += 1; \ 19062306a36Sopenharmony_ci r0 &= 1; \ 19162306a36Sopenharmony_ci if r0 < 2 goto l1_%=; \ 19262306a36Sopenharmony_ci exit; \ 19362306a36Sopenharmony_cil1_%=: r0 += 1; \ 19462306a36Sopenharmony_ci r0 &= 1; \ 19562306a36Sopenharmony_ci if r0 < 2 goto l2_%=; \ 19662306a36Sopenharmony_ci exit; \ 19762306a36Sopenharmony_ci" ::: __clobber_all); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciSEC("xdp") 20162306a36Sopenharmony_ci__description("not-taken loop with back jump to 1st insn") 20262306a36Sopenharmony_ci__success __retval(123) 20362306a36Sopenharmony_ci__naked void back_jump_to_1st_insn_1(void) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci asm volatile (" \ 20662306a36Sopenharmony_cil0_%=: r0 = 123; \ 20762306a36Sopenharmony_ci if r0 == 4 goto l0_%=; \ 20862306a36Sopenharmony_ci exit; \ 20962306a36Sopenharmony_ci" ::: __clobber_all); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciSEC("xdp") 21362306a36Sopenharmony_ci__description("taken loop with back jump to 1st insn") 21462306a36Sopenharmony_ci__success __retval(55) 21562306a36Sopenharmony_ci__naked void back_jump_to_1st_insn_2(void) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci asm volatile (" \ 21862306a36Sopenharmony_ci r1 = 10; \ 21962306a36Sopenharmony_ci r2 = 0; \ 22062306a36Sopenharmony_ci call back_jump_to_1st_insn_2__1; \ 22162306a36Sopenharmony_ci exit; \ 22262306a36Sopenharmony_ci" ::: __clobber_all); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic __naked __noinline __attribute__((used)) 22662306a36Sopenharmony_civoid back_jump_to_1st_insn_2__1(void) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci asm volatile (" \ 22962306a36Sopenharmony_cil0_%=: r2 += r1; \ 23062306a36Sopenharmony_ci r1 -= 1; \ 23162306a36Sopenharmony_ci if r1 != 0 goto l0_%=; \ 23262306a36Sopenharmony_ci r0 = r2; \ 23362306a36Sopenharmony_ci exit; \ 23462306a36Sopenharmony_ci" ::: __clobber_all); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciSEC("xdp") 23862306a36Sopenharmony_ci__description("taken loop with back jump to 1st insn, 2") 23962306a36Sopenharmony_ci__success __retval(55) 24062306a36Sopenharmony_ci__naked void jump_to_1st_insn_2(void) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci asm volatile (" \ 24362306a36Sopenharmony_ci r1 = 10; \ 24462306a36Sopenharmony_ci r2 = 0; \ 24562306a36Sopenharmony_ci call jump_to_1st_insn_2__1; \ 24662306a36Sopenharmony_ci exit; \ 24762306a36Sopenharmony_ci" ::: __clobber_all); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic __naked __noinline __attribute__((used)) 25162306a36Sopenharmony_civoid jump_to_1st_insn_2__1(void) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci asm volatile (" \ 25462306a36Sopenharmony_cil0_%=: r2 += r1; \ 25562306a36Sopenharmony_ci r1 -= 1; \ 25662306a36Sopenharmony_ci if w1 != 0 goto l0_%=; \ 25762306a36Sopenharmony_ci r0 = r2; \ 25862306a36Sopenharmony_ci exit; \ 25962306a36Sopenharmony_ci" ::: __clobber_all); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 263