Linux 6.9-rc1
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / verifier / bpf_loop_inline.c
1 #define BTF_TYPES \
2         .btf_strings = "\0int\0i\0ctx\0callback\0main\0", \
3         .btf_types = { \
4         /* 1: int   */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \
5         /* 2: int*  */ BTF_PTR_ENC(1), \
6         /* 3: void* */ BTF_PTR_ENC(0), \
7         /* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \
8                 BTF_FUNC_PROTO_ARG_ENC(7, 3), \
9         /* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \
10                 BTF_FUNC_PROTO_ARG_ENC(5, 1), \
11                 BTF_FUNC_PROTO_ARG_ENC(7, 2), \
12         /* 6: main      */ BTF_FUNC_ENC(20, 4), \
13         /* 7: callback  */ BTF_FUNC_ENC(11, 5), \
14         BTF_END_RAW \
15         }
16
17 #define MAIN_TYPE       6
18 #define CALLBACK_TYPE   7
19
20 /* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF
21  * fields for pseudo calls
22  */
23 #define PSEUDO_CALL_INSN() \
24         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \
25                      INSN_OFF_MASK, INSN_IMM_MASK)
26
27 /* can't use BPF_FUNC_loop constant,
28  * do_mix_fixups adjusts the IMM field
29  */
30 #define HELPER_CALL_INSN() \
31         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK)
32
33 {
34         "inline simple bpf_loop call",
35         .insns = {
36         /* main */
37         /* force verifier state branching to verify logic on first and
38          * subsequent bpf_loop insn processing steps
39          */
40         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
41         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2),
42         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
43         BPF_JMP_IMM(BPF_JA, 0, 0, 1),
44         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
45
46         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
47         BPF_RAW_INSN(0, 0, 0, 0, 0),
48         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
49         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
50         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
51         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
52         BPF_EXIT_INSN(),
53         /* callback */
54         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
55         BPF_EXIT_INSN(),
56         },
57         .expected_insns = { PSEUDO_CALL_INSN() },
58         .unexpected_insns = { HELPER_CALL_INSN() },
59         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
60         .flags = F_NEEDS_JIT_ENABLED,
61         .result = ACCEPT,
62         .runs = 0,
63         .func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } },
64         .func_info_cnt = 2,
65         BTF_TYPES
66 },
67 {
68         "don't inline bpf_loop call, flags non-zero",
69         .insns = {
70         /* main */
71         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
72         BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0),
73         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
74         BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0),
75         BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9),
76         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
77         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0),
78         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
79         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7),
80         BPF_RAW_INSN(0, 0, 0, 0, 0),
81         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
82         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
83         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
84         BPF_EXIT_INSN(),
85         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1),
86         BPF_JMP_IMM(BPF_JA, 0, 0, -10),
87         /* callback */
88         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
89         BPF_EXIT_INSN(),
90         },
91         .expected_insns = { HELPER_CALL_INSN() },
92         .unexpected_insns = { PSEUDO_CALL_INSN() },
93         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
94         .flags = F_NEEDS_JIT_ENABLED,
95         .result = ACCEPT,
96         .runs = 0,
97         .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
98         .func_info_cnt = 2,
99         BTF_TYPES
100 },
101 {
102         "don't inline bpf_loop call, callback non-constant",
103         .insns = {
104         /* main */
105         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
106         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */
107
108         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
109         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10),
110         BPF_RAW_INSN(0, 0, 0, 0, 0),
111         BPF_JMP_IMM(BPF_JA, 0, 0, 3),
112
113         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
114         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
115         BPF_RAW_INSN(0, 0, 0, 0, 0),
116
117         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
118         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
119         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
120         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
121         BPF_EXIT_INSN(),
122         /* callback */
123         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
124         BPF_EXIT_INSN(),
125         /* callback #2 */
126         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
127         BPF_EXIT_INSN(),
128         },
129         .expected_insns = { HELPER_CALL_INSN() },
130         .unexpected_insns = { PSEUDO_CALL_INSN() },
131         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
132         .flags = F_NEEDS_JIT_ENABLED,
133         .result = ACCEPT,
134         .runs = 0,
135         .func_info = {
136                 { 0, MAIN_TYPE },
137                 { 14, CALLBACK_TYPE },
138                 { 16, CALLBACK_TYPE }
139         },
140         .func_info_cnt = 3,
141         BTF_TYPES
142 },
143 {
144         "bpf_loop_inline and a dead func",
145         .insns = {
146         /* main */
147
148         /* A reference to callback #1 to make verifier count it as a func.
149          * This reference is overwritten below and callback #1 is dead.
150          */
151         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9),
152         BPF_RAW_INSN(0, 0, 0, 0, 0),
153         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
154         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
155         BPF_RAW_INSN(0, 0, 0, 0, 0),
156         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
157         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
158         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
159         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
160         BPF_EXIT_INSN(),
161         /* callback */
162         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
163         BPF_EXIT_INSN(),
164         /* callback #2 */
165         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
166         BPF_EXIT_INSN(),
167         },
168         .expected_insns = { PSEUDO_CALL_INSN() },
169         .unexpected_insns = { HELPER_CALL_INSN() },
170         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
171         .flags = F_NEEDS_JIT_ENABLED,
172         .result = ACCEPT,
173         .runs = 0,
174         .func_info = {
175                 { 0, MAIN_TYPE },
176                 { 10, CALLBACK_TYPE },
177                 { 12, CALLBACK_TYPE }
178         },
179         .func_info_cnt = 3,
180         BTF_TYPES
181 },
182 {
183         "bpf_loop_inline stack locations for loop vars",
184         .insns = {
185         /* main */
186         BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
187         /* bpf_loop call #1 */
188         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
189         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22),
190         BPF_RAW_INSN(0, 0, 0, 0, 0),
191         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
192         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
193         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
194         /* bpf_loop call #2 */
195         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
196         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16),
197         BPF_RAW_INSN(0, 0, 0, 0, 0),
198         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
199         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
200         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
201         /* call func and exit */
202         BPF_CALL_REL(2),
203         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
204         BPF_EXIT_INSN(),
205         /* func */
206         BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
207         BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
208         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
209         BPF_RAW_INSN(0, 0, 0, 0, 0),
210         BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
211         BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
212         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
213         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
214         BPF_EXIT_INSN(),
215         /* callback */
216         BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
217         BPF_EXIT_INSN(),
218         },
219         .expected_insns = {
220         BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
221         SKIP_INSNS(),
222         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
223         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
224         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
225         SKIP_INSNS(),
226         /* offsets are the same as in the first call */
227         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
228         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
229         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
230         SKIP_INSNS(),
231         BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
232         SKIP_INSNS(),
233         /* offsets differ from main because of different offset
234          * in BPF_ST_MEM instruction
235          */
236         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56),
237         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48),
238         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40),
239         },
240         .unexpected_insns = { HELPER_CALL_INSN() },
241         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
242         .flags = F_NEEDS_JIT_ENABLED,
243         .result = ACCEPT,
244         .func_info = {
245                 { 0, MAIN_TYPE },
246                 { 16, MAIN_TYPE },
247                 { 25, CALLBACK_TYPE },
248         },
249         .func_info_cnt = 3,
250         BTF_TYPES
251 },
252 {
253         "inline bpf_loop call in a big program",
254         .insns = {},
255         .fill_helper = bpf_fill_big_prog_with_loop_1,
256         .expected_insns = { PSEUDO_CALL_INSN() },
257         .unexpected_insns = { HELPER_CALL_INSN() },
258         .result = ACCEPT,
259         .prog_type = BPF_PROG_TYPE_TRACEPOINT,
260         .flags = F_NEEDS_JIT_ENABLED,
261         .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
262         .func_info_cnt = 2,
263         BTF_TYPES
264 },
265
266 #undef HELPER_CALL_INSN
267 #undef PSEUDO_CALL_INSN
268 #undef CALLBACK_TYPE
269 #undef MAIN_TYPE
270 #undef BTF_TYPES