1// SPDX-License-Identifier: GPL-2.0
2/* Converted from tools/testing/selftests/bpf/verifier/cfg.c */
3
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include "bpf_misc.h"
7
8SEC("socket")
9__description("unreachable")
10__failure __msg("unreachable")
11__failure_unpriv
12__naked void unreachable(void)
13{
14	asm volatile ("					\
15	exit;						\
16	exit;						\
17"	::: __clobber_all);
18}
19
20SEC("socket")
21__description("unreachable2")
22__failure __msg("unreachable")
23__failure_unpriv
24__naked void unreachable2(void)
25{
26	asm volatile ("					\
27	goto l0_%=;					\
28	goto l0_%=;					\
29l0_%=:	exit;						\
30"	::: __clobber_all);
31}
32
33SEC("socket")
34__description("out of range jump")
35__failure __msg("jump out of range")
36__failure_unpriv
37__naked void out_of_range_jump(void)
38{
39	asm volatile ("					\
40	goto l0_%=;					\
41	exit;						\
42l0_%=:							\
43"	::: __clobber_all);
44}
45
46SEC("socket")
47__description("out of range jump2")
48__failure __msg("jump out of range")
49__failure_unpriv
50__naked void out_of_range_jump2(void)
51{
52	asm volatile ("					\
53	goto -2;					\
54	exit;						\
55"	::: __clobber_all);
56}
57
58SEC("socket")
59__description("loop (back-edge)")
60__failure __msg("unreachable insn 1")
61__msg_unpriv("back-edge")
62__naked void loop_back_edge(void)
63{
64	asm volatile ("					\
65l0_%=:	goto l0_%=;					\
66	exit;						\
67"	::: __clobber_all);
68}
69
70SEC("socket")
71__description("loop2 (back-edge)")
72__failure __msg("unreachable insn 4")
73__msg_unpriv("back-edge")
74__naked void loop2_back_edge(void)
75{
76	asm volatile ("					\
77l0_%=:	r1 = r0;					\
78	r2 = r0;					\
79	r3 = r0;					\
80	goto l0_%=;					\
81	exit;						\
82"	::: __clobber_all);
83}
84
85SEC("socket")
86__description("conditional loop")
87__failure __msg("infinite loop detected")
88__msg_unpriv("back-edge")
89__naked void conditional_loop(void)
90{
91	asm volatile ("					\
92	r0 = r1;					\
93l0_%=:	r2 = r0;					\
94	r3 = r0;					\
95	if r1 == 0 goto l0_%=;				\
96	exit;						\
97"	::: __clobber_all);
98}
99
100SEC("socket")
101__description("conditional loop (2)")
102__success
103__failure_unpriv __msg_unpriv("back-edge from insn 10 to 11")
104__naked void conditional_loop2(void)
105{
106	asm volatile ("					\
107	r9 = 2 ll;					\
108	r3 = 0x20 ll;					\
109	r4 = 0x35 ll;					\
110	r8 = r4;					\
111	goto l1_%=;					\
112l0_%=:	r9 -= r3;					\
113	r9 -= r4;					\
114	r9 -= r8;					\
115l1_%=:	r8 += r4;					\
116	if r8 < 0x64 goto l0_%=;			\
117	r0 = r9;					\
118	exit;						\
119"	::: __clobber_all);
120}
121
122SEC("socket")
123__description("unconditional loop after conditional jump")
124__failure __msg("infinite loop detected")
125__failure_unpriv __msg_unpriv("back-edge from insn 3 to 2")
126__naked void uncond_loop_after_cond_jmp(void)
127{
128	asm volatile ("					\
129	r0 = 0;						\
130	if r0 > 0 goto l1_%=;				\
131l0_%=:	r0 = 1;						\
132	goto l0_%=;					\
133l1_%=:	exit;						\
134"	::: __clobber_all);
135}
136
137
138__naked __noinline __used
139static unsigned long never_ending_subprog()
140{
141	asm volatile ("					\
142	r0 = r1;					\
143	goto -1;					\
144"	::: __clobber_all);
145}
146
147SEC("socket")
148__description("unconditional loop after conditional jump")
149/* infinite loop is detected *after* check_cfg() */
150__failure __msg("infinite loop detected")
151__naked void uncond_loop_in_subprog_after_cond_jmp(void)
152{
153	asm volatile ("					\
154	r0 = 0;						\
155	if r0 > 0 goto l1_%=;				\
156l0_%=:	r0 += 1;					\
157	call never_ending_subprog;			\
158l1_%=:	exit;						\
159"	::: __clobber_all);
160}
161
162char _license[] SEC("license") = "GPL";
163