1*57400dccSAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2*57400dccSAndrii Nakryiko /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3*57400dccSAndrii Nakryiko 
4*57400dccSAndrii Nakryiko #include <stdbool.h>
5*57400dccSAndrii Nakryiko #include <linux/bpf.h>
6*57400dccSAndrii Nakryiko #include <bpf/bpf_helpers.h>
7*57400dccSAndrii Nakryiko #include "bpf_misc.h"
8*57400dccSAndrii Nakryiko 
9*57400dccSAndrii Nakryiko #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
10*57400dccSAndrii Nakryiko 
11*57400dccSAndrii Nakryiko static volatile int zero = 0;
12*57400dccSAndrii Nakryiko 
13*57400dccSAndrii Nakryiko int my_pid;
14*57400dccSAndrii Nakryiko int arr[256];
15*57400dccSAndrii Nakryiko int small_arr[16] SEC(".data.small_arr");
16*57400dccSAndrii Nakryiko 
17*57400dccSAndrii Nakryiko #ifdef REAL_TEST
18*57400dccSAndrii Nakryiko #define MY_PID_GUARD() if (my_pid != (bpf_get_current_pid_tgid() >> 32)) return 0
19*57400dccSAndrii Nakryiko #else
20*57400dccSAndrii Nakryiko #define MY_PID_GUARD() ({ })
21*57400dccSAndrii Nakryiko #endif
22*57400dccSAndrii Nakryiko 
23*57400dccSAndrii Nakryiko SEC("?raw_tp")
24*57400dccSAndrii Nakryiko __failure __msg("math between map_value pointer and register with unbounded min value is not allowed")
25*57400dccSAndrii Nakryiko int iter_err_unsafe_c_loop(const void *ctx)
26*57400dccSAndrii Nakryiko {
27*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
28*57400dccSAndrii Nakryiko 	int *v, i = zero; /* obscure initial value of i */
29*57400dccSAndrii Nakryiko 
30*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
31*57400dccSAndrii Nakryiko 
32*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 1000);
33*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
34*57400dccSAndrii Nakryiko 		i++;
35*57400dccSAndrii Nakryiko 	}
36*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
37*57400dccSAndrii Nakryiko 
38*57400dccSAndrii Nakryiko 	small_arr[i] = 123; /* invalid */
39*57400dccSAndrii Nakryiko 
40*57400dccSAndrii Nakryiko 	return 0;
41*57400dccSAndrii Nakryiko }
42*57400dccSAndrii Nakryiko 
43*57400dccSAndrii Nakryiko SEC("?raw_tp")
44*57400dccSAndrii Nakryiko __failure __msg("unbounded memory access")
45*57400dccSAndrii Nakryiko int iter_err_unsafe_asm_loop(const void *ctx)
46*57400dccSAndrii Nakryiko {
47*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
48*57400dccSAndrii Nakryiko 	int *v, i = 0;
49*57400dccSAndrii Nakryiko 
50*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
51*57400dccSAndrii Nakryiko 
52*57400dccSAndrii Nakryiko 	asm volatile (
53*57400dccSAndrii Nakryiko 		"r6 = %[zero];" /* iteration counter */
54*57400dccSAndrii Nakryiko 		"r1 = %[it];" /* iterator state */
55*57400dccSAndrii Nakryiko 		"r2 = 0;"
56*57400dccSAndrii Nakryiko 		"r3 = 1000;"
57*57400dccSAndrii Nakryiko 		"r4 = 1;"
58*57400dccSAndrii Nakryiko 		"call %[bpf_iter_num_new];"
59*57400dccSAndrii Nakryiko 	"loop:"
60*57400dccSAndrii Nakryiko 		"r1 = %[it];"
61*57400dccSAndrii Nakryiko 		"call %[bpf_iter_num_next];"
62*57400dccSAndrii Nakryiko 		"if r0 == 0 goto out;"
63*57400dccSAndrii Nakryiko 		"r6 += 1;"
64*57400dccSAndrii Nakryiko 		"goto loop;"
65*57400dccSAndrii Nakryiko 	"out:"
66*57400dccSAndrii Nakryiko 		"r1 = %[it];"
67*57400dccSAndrii Nakryiko 		"call %[bpf_iter_num_destroy];"
68*57400dccSAndrii Nakryiko 		"r1 = %[small_arr];"
69*57400dccSAndrii Nakryiko 		"r2 = r6;"
70*57400dccSAndrii Nakryiko 		"r2 <<= 2;"
71*57400dccSAndrii Nakryiko 		"r1 += r2;"
72*57400dccSAndrii Nakryiko 		"*(u32 *)(r1 + 0) = r6;" /* invalid */
73*57400dccSAndrii Nakryiko 		:
74*57400dccSAndrii Nakryiko 		: [it]"r"(&it),
75*57400dccSAndrii Nakryiko 		  [small_arr]"p"(small_arr),
76*57400dccSAndrii Nakryiko 		  [zero]"p"(zero),
77*57400dccSAndrii Nakryiko 		  __imm(bpf_iter_num_new),
78*57400dccSAndrii Nakryiko 		  __imm(bpf_iter_num_next),
79*57400dccSAndrii Nakryiko 		  __imm(bpf_iter_num_destroy)
80*57400dccSAndrii Nakryiko 		: __clobber_common, "r6"
81*57400dccSAndrii Nakryiko 	);
82*57400dccSAndrii Nakryiko 
83*57400dccSAndrii Nakryiko 	return 0;
84*57400dccSAndrii Nakryiko }
85*57400dccSAndrii Nakryiko 
86*57400dccSAndrii Nakryiko SEC("raw_tp")
87*57400dccSAndrii Nakryiko __success
88*57400dccSAndrii Nakryiko int iter_while_loop(const void *ctx)
89*57400dccSAndrii Nakryiko {
90*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
91*57400dccSAndrii Nakryiko 	int *v, i;
92*57400dccSAndrii Nakryiko 
93*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
94*57400dccSAndrii Nakryiko 
95*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 3);
96*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
97*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v);
98*57400dccSAndrii Nakryiko 	}
99*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
100*57400dccSAndrii Nakryiko 
101*57400dccSAndrii Nakryiko 	return 0;
102*57400dccSAndrii Nakryiko }
103*57400dccSAndrii Nakryiko 
104*57400dccSAndrii Nakryiko SEC("raw_tp")
105*57400dccSAndrii Nakryiko __success
106*57400dccSAndrii Nakryiko int iter_while_loop_auto_cleanup(const void *ctx)
107*57400dccSAndrii Nakryiko {
108*57400dccSAndrii Nakryiko 	__attribute__((cleanup(bpf_iter_num_destroy))) struct bpf_iter_num it;
109*57400dccSAndrii Nakryiko 	int *v, i;
110*57400dccSAndrii Nakryiko 
111*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
112*57400dccSAndrii Nakryiko 
113*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 3);
114*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
115*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v);
116*57400dccSAndrii Nakryiko 	}
117*57400dccSAndrii Nakryiko 	/* (!) no explicit bpf_iter_num_destroy() */
118*57400dccSAndrii Nakryiko 
119*57400dccSAndrii Nakryiko 	return 0;
120*57400dccSAndrii Nakryiko }
121*57400dccSAndrii Nakryiko 
122*57400dccSAndrii Nakryiko SEC("raw_tp")
123*57400dccSAndrii Nakryiko __success
124*57400dccSAndrii Nakryiko int iter_for_loop(const void *ctx)
125*57400dccSAndrii Nakryiko {
126*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
127*57400dccSAndrii Nakryiko 	int *v, i;
128*57400dccSAndrii Nakryiko 
129*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
130*57400dccSAndrii Nakryiko 
131*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 5, 10);
132*57400dccSAndrii Nakryiko 	for (v = bpf_iter_num_next(&it); v; v = bpf_iter_num_next(&it)) {
133*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v);
134*57400dccSAndrii Nakryiko 	}
135*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
136*57400dccSAndrii Nakryiko 
137*57400dccSAndrii Nakryiko 	return 0;
138*57400dccSAndrii Nakryiko }
139*57400dccSAndrii Nakryiko 
140*57400dccSAndrii Nakryiko SEC("raw_tp")
141*57400dccSAndrii Nakryiko __success
142*57400dccSAndrii Nakryiko int iter_bpf_for_each_macro(const void *ctx)
143*57400dccSAndrii Nakryiko {
144*57400dccSAndrii Nakryiko 	int *v;
145*57400dccSAndrii Nakryiko 
146*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
147*57400dccSAndrii Nakryiko 
148*57400dccSAndrii Nakryiko 	bpf_for_each(num, v, 5, 10) {
149*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v);
150*57400dccSAndrii Nakryiko 	}
151*57400dccSAndrii Nakryiko 
152*57400dccSAndrii Nakryiko 	return 0;
153*57400dccSAndrii Nakryiko }
154*57400dccSAndrii Nakryiko 
155*57400dccSAndrii Nakryiko SEC("raw_tp")
156*57400dccSAndrii Nakryiko __success
157*57400dccSAndrii Nakryiko int iter_bpf_for_macro(const void *ctx)
158*57400dccSAndrii Nakryiko {
159*57400dccSAndrii Nakryiko 	int i;
160*57400dccSAndrii Nakryiko 
161*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
162*57400dccSAndrii Nakryiko 
163*57400dccSAndrii Nakryiko 	bpf_for(i, 5, 10) {
164*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E2 VAL: v=%d", i);
165*57400dccSAndrii Nakryiko 	}
166*57400dccSAndrii Nakryiko 
167*57400dccSAndrii Nakryiko 	return 0;
168*57400dccSAndrii Nakryiko }
169*57400dccSAndrii Nakryiko 
170*57400dccSAndrii Nakryiko SEC("raw_tp")
171*57400dccSAndrii Nakryiko __success
172*57400dccSAndrii Nakryiko int iter_pragma_unroll_loop(const void *ctx)
173*57400dccSAndrii Nakryiko {
174*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
175*57400dccSAndrii Nakryiko 	int *v, i;
176*57400dccSAndrii Nakryiko 
177*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
178*57400dccSAndrii Nakryiko 
179*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 2);
180*57400dccSAndrii Nakryiko #pragma nounroll
181*57400dccSAndrii Nakryiko 	for (i = 0; i < 3; i++) {
182*57400dccSAndrii Nakryiko 		v = bpf_iter_num_next(&it);
183*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1);
184*57400dccSAndrii Nakryiko 	}
185*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
186*57400dccSAndrii Nakryiko 
187*57400dccSAndrii Nakryiko 	return 0;
188*57400dccSAndrii Nakryiko }
189*57400dccSAndrii Nakryiko 
190*57400dccSAndrii Nakryiko SEC("raw_tp")
191*57400dccSAndrii Nakryiko __success
192*57400dccSAndrii Nakryiko int iter_manual_unroll_loop(const void *ctx)
193*57400dccSAndrii Nakryiko {
194*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
195*57400dccSAndrii Nakryiko 	int *v, i;
196*57400dccSAndrii Nakryiko 
197*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
198*57400dccSAndrii Nakryiko 
199*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 100, 200);
200*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
201*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
202*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
203*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
204*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
205*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
206*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
207*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d\n", v ? *v : -1);
208*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
209*57400dccSAndrii Nakryiko 
210*57400dccSAndrii Nakryiko 	return 0;
211*57400dccSAndrii Nakryiko }
212*57400dccSAndrii Nakryiko 
213*57400dccSAndrii Nakryiko SEC("raw_tp")
214*57400dccSAndrii Nakryiko __success
215*57400dccSAndrii Nakryiko int iter_multiple_sequential_loops(const void *ctx)
216*57400dccSAndrii Nakryiko {
217*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
218*57400dccSAndrii Nakryiko 	int *v, i;
219*57400dccSAndrii Nakryiko 
220*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
221*57400dccSAndrii Nakryiko 
222*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 3);
223*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
224*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v);
225*57400dccSAndrii Nakryiko 	}
226*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
227*57400dccSAndrii Nakryiko 
228*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 5, 10);
229*57400dccSAndrii Nakryiko 	for (v = bpf_iter_num_next(&it); v; v = bpf_iter_num_next(&it)) {
230*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v);
231*57400dccSAndrii Nakryiko 	}
232*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
233*57400dccSAndrii Nakryiko 
234*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 2);
235*57400dccSAndrii Nakryiko #pragma nounroll
236*57400dccSAndrii Nakryiko 	for (i = 0; i < 3; i++) {
237*57400dccSAndrii Nakryiko 		v = bpf_iter_num_next(&it);
238*57400dccSAndrii Nakryiko 		bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1);
239*57400dccSAndrii Nakryiko 	}
240*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
241*57400dccSAndrii Nakryiko 
242*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 100, 200);
243*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
244*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
245*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
246*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
247*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
248*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1);
249*57400dccSAndrii Nakryiko 	v = bpf_iter_num_next(&it);
250*57400dccSAndrii Nakryiko 	bpf_printk("ITER_BASIC: E4 VAL: v=%d\n", v ? *v : -1);
251*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
252*57400dccSAndrii Nakryiko 
253*57400dccSAndrii Nakryiko 	return 0;
254*57400dccSAndrii Nakryiko }
255*57400dccSAndrii Nakryiko 
256*57400dccSAndrii Nakryiko SEC("raw_tp")
257*57400dccSAndrii Nakryiko __success
258*57400dccSAndrii Nakryiko int iter_limit_cond_break_loop(const void *ctx)
259*57400dccSAndrii Nakryiko {
260*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
261*57400dccSAndrii Nakryiko 	int *v, i = 0, sum = 0;
262*57400dccSAndrii Nakryiko 
263*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
264*57400dccSAndrii Nakryiko 
265*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 10);
266*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
267*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SIMPLE: i=%d v=%d", i, *v);
268*57400dccSAndrii Nakryiko 		sum += *v;
269*57400dccSAndrii Nakryiko 
270*57400dccSAndrii Nakryiko 		i++;
271*57400dccSAndrii Nakryiko 		if (i > 3)
272*57400dccSAndrii Nakryiko 			break;
273*57400dccSAndrii Nakryiko 	}
274*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
275*57400dccSAndrii Nakryiko 
276*57400dccSAndrii Nakryiko 	bpf_printk("ITER_SIMPLE: sum=%d\n", sum);
277*57400dccSAndrii Nakryiko 
278*57400dccSAndrii Nakryiko 	return 0;
279*57400dccSAndrii Nakryiko }
280*57400dccSAndrii Nakryiko 
281*57400dccSAndrii Nakryiko SEC("raw_tp")
282*57400dccSAndrii Nakryiko __success
283*57400dccSAndrii Nakryiko int iter_obfuscate_counter(const void *ctx)
284*57400dccSAndrii Nakryiko {
285*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
286*57400dccSAndrii Nakryiko 	int *v, sum = 0;
287*57400dccSAndrii Nakryiko 	/* Make i's initial value unknowable for verifier to prevent it from
288*57400dccSAndrii Nakryiko 	 * pruning if/else branch inside the loop body and marking i as precise.
289*57400dccSAndrii Nakryiko 	 */
290*57400dccSAndrii Nakryiko 	int i = zero;
291*57400dccSAndrii Nakryiko 
292*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
293*57400dccSAndrii Nakryiko 
294*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 10);
295*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
296*57400dccSAndrii Nakryiko 		int x;
297*57400dccSAndrii Nakryiko 
298*57400dccSAndrii Nakryiko 		i += 1;
299*57400dccSAndrii Nakryiko 
300*57400dccSAndrii Nakryiko 		/* If we initialized i as `int i = 0;` above, verifier would
301*57400dccSAndrii Nakryiko 		 * track that i becomes 1 on first iteration after increment
302*57400dccSAndrii Nakryiko 		 * above, and here verifier would eagerly prune else branch
303*57400dccSAndrii Nakryiko 		 * and mark i as precise, ruining open-coded iterator logic
304*57400dccSAndrii Nakryiko 		 * completely, as each next iteration would have a different
305*57400dccSAndrii Nakryiko 		 * *precise* value of i, and thus there would be no
306*57400dccSAndrii Nakryiko 		 * convergence of state. This would result in reaching maximum
307*57400dccSAndrii Nakryiko 		 * instruction limit, no matter what the limit is.
308*57400dccSAndrii Nakryiko 		 */
309*57400dccSAndrii Nakryiko 		if (i == 1)
310*57400dccSAndrii Nakryiko 			x = 123;
311*57400dccSAndrii Nakryiko 		else
312*57400dccSAndrii Nakryiko 			x = i * 3 + 1;
313*57400dccSAndrii Nakryiko 
314*57400dccSAndrii Nakryiko 		bpf_printk("ITER_OBFUSCATE_COUNTER: i=%d v=%d x=%d", i, *v, x);
315*57400dccSAndrii Nakryiko 
316*57400dccSAndrii Nakryiko 		sum += x;
317*57400dccSAndrii Nakryiko 	}
318*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
319*57400dccSAndrii Nakryiko 
320*57400dccSAndrii Nakryiko 	bpf_printk("ITER_OBFUSCATE_COUNTER: sum=%d\n", sum);
321*57400dccSAndrii Nakryiko 
322*57400dccSAndrii Nakryiko 	return 0;
323*57400dccSAndrii Nakryiko }
324*57400dccSAndrii Nakryiko 
325*57400dccSAndrii Nakryiko SEC("raw_tp")
326*57400dccSAndrii Nakryiko __success
327*57400dccSAndrii Nakryiko int iter_search_loop(const void *ctx)
328*57400dccSAndrii Nakryiko {
329*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
330*57400dccSAndrii Nakryiko 	int *v, *elem = NULL;
331*57400dccSAndrii Nakryiko 	bool found = false;
332*57400dccSAndrii Nakryiko 
333*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
334*57400dccSAndrii Nakryiko 
335*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, 10);
336*57400dccSAndrii Nakryiko 
337*57400dccSAndrii Nakryiko 	while ((v = bpf_iter_num_next(&it))) {
338*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SEARCH_LOOP: v=%d", *v);
339*57400dccSAndrii Nakryiko 
340*57400dccSAndrii Nakryiko 		if (*v == 2) {
341*57400dccSAndrii Nakryiko 			found = true;
342*57400dccSAndrii Nakryiko 			elem = v;
343*57400dccSAndrii Nakryiko 			barrier_var(elem);
344*57400dccSAndrii Nakryiko 		}
345*57400dccSAndrii Nakryiko 	}
346*57400dccSAndrii Nakryiko 
347*57400dccSAndrii Nakryiko 	/* should fail to verify if bpf_iter_num_destroy() is here */
348*57400dccSAndrii Nakryiko 
349*57400dccSAndrii Nakryiko 	if (found)
350*57400dccSAndrii Nakryiko 		/* here found element will be wrong, we should have copied
351*57400dccSAndrii Nakryiko 		 * value to a variable, but here we want to make sure we can
352*57400dccSAndrii Nakryiko 		 * access memory after the loop anyways
353*57400dccSAndrii Nakryiko 		 */
354*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SEARCH_LOOP: FOUND IT = %d!\n", *elem);
355*57400dccSAndrii Nakryiko 	else
356*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SEARCH_LOOP: NOT FOUND IT!\n");
357*57400dccSAndrii Nakryiko 
358*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
359*57400dccSAndrii Nakryiko 
360*57400dccSAndrii Nakryiko 	return 0;
361*57400dccSAndrii Nakryiko }
362*57400dccSAndrii Nakryiko 
363*57400dccSAndrii Nakryiko SEC("raw_tp")
364*57400dccSAndrii Nakryiko __success
365*57400dccSAndrii Nakryiko int iter_array_fill(const void *ctx)
366*57400dccSAndrii Nakryiko {
367*57400dccSAndrii Nakryiko 	int sum, i;
368*57400dccSAndrii Nakryiko 
369*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
370*57400dccSAndrii Nakryiko 
371*57400dccSAndrii Nakryiko 	bpf_for(i, 0, ARRAY_SIZE(arr)) {
372*57400dccSAndrii Nakryiko 		arr[i] = i * 2;
373*57400dccSAndrii Nakryiko 	}
374*57400dccSAndrii Nakryiko 
375*57400dccSAndrii Nakryiko 	sum = 0;
376*57400dccSAndrii Nakryiko 	bpf_for(i, 0, ARRAY_SIZE(arr)) {
377*57400dccSAndrii Nakryiko 		sum += arr[i];
378*57400dccSAndrii Nakryiko 	}
379*57400dccSAndrii Nakryiko 
380*57400dccSAndrii Nakryiko 	bpf_printk("ITER_ARRAY_FILL: sum=%d (should be %d)\n", sum, 255 * 256);
381*57400dccSAndrii Nakryiko 
382*57400dccSAndrii Nakryiko 	return 0;
383*57400dccSAndrii Nakryiko }
384*57400dccSAndrii Nakryiko 
385*57400dccSAndrii Nakryiko static int arr2d[4][5];
386*57400dccSAndrii Nakryiko static int arr2d_row_sums[4];
387*57400dccSAndrii Nakryiko static int arr2d_col_sums[5];
388*57400dccSAndrii Nakryiko 
389*57400dccSAndrii Nakryiko SEC("raw_tp")
390*57400dccSAndrii Nakryiko __success
391*57400dccSAndrii Nakryiko int iter_nested_iters(const void *ctx)
392*57400dccSAndrii Nakryiko {
393*57400dccSAndrii Nakryiko 	int sum, row, col;
394*57400dccSAndrii Nakryiko 
395*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
396*57400dccSAndrii Nakryiko 
397*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
398*57400dccSAndrii Nakryiko 		bpf_for( col, 0, ARRAY_SIZE(arr2d[0])) {
399*57400dccSAndrii Nakryiko 			arr2d[row][col] = row * col;
400*57400dccSAndrii Nakryiko 		}
401*57400dccSAndrii Nakryiko 	}
402*57400dccSAndrii Nakryiko 
403*57400dccSAndrii Nakryiko 	/* zero-initialize sums */
404*57400dccSAndrii Nakryiko 	sum = 0;
405*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
406*57400dccSAndrii Nakryiko 		arr2d_row_sums[row] = 0;
407*57400dccSAndrii Nakryiko 	}
408*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
409*57400dccSAndrii Nakryiko 		arr2d_col_sums[col] = 0;
410*57400dccSAndrii Nakryiko 	}
411*57400dccSAndrii Nakryiko 
412*57400dccSAndrii Nakryiko 	/* calculate sums */
413*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
414*57400dccSAndrii Nakryiko 		bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
415*57400dccSAndrii Nakryiko 			sum += arr2d[row][col];
416*57400dccSAndrii Nakryiko 			arr2d_row_sums[row] += arr2d[row][col];
417*57400dccSAndrii Nakryiko 			arr2d_col_sums[col] += arr2d[row][col];
418*57400dccSAndrii Nakryiko 		}
419*57400dccSAndrii Nakryiko 	}
420*57400dccSAndrii Nakryiko 
421*57400dccSAndrii Nakryiko 	bpf_printk("ITER_NESTED_ITERS: total sum=%d", sum);
422*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
423*57400dccSAndrii Nakryiko 		bpf_printk("ITER_NESTED_ITERS: row #%d sum=%d", row, arr2d_row_sums[row]);
424*57400dccSAndrii Nakryiko 	}
425*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
426*57400dccSAndrii Nakryiko 		bpf_printk("ITER_NESTED_ITERS: col #%d sum=%d%s",
427*57400dccSAndrii Nakryiko 			   col, arr2d_col_sums[col],
428*57400dccSAndrii Nakryiko 			   col == ARRAY_SIZE(arr2d[0]) - 1 ? "\n" : "");
429*57400dccSAndrii Nakryiko 	}
430*57400dccSAndrii Nakryiko 
431*57400dccSAndrii Nakryiko 	return 0;
432*57400dccSAndrii Nakryiko }
433*57400dccSAndrii Nakryiko 
434*57400dccSAndrii Nakryiko SEC("raw_tp")
435*57400dccSAndrii Nakryiko __success
436*57400dccSAndrii Nakryiko int iter_nested_deeply_iters(const void *ctx)
437*57400dccSAndrii Nakryiko {
438*57400dccSAndrii Nakryiko 	int sum = 0;
439*57400dccSAndrii Nakryiko 
440*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
441*57400dccSAndrii Nakryiko 
442*57400dccSAndrii Nakryiko 	bpf_repeat(10) {
443*57400dccSAndrii Nakryiko 		bpf_repeat(10) {
444*57400dccSAndrii Nakryiko 			bpf_repeat(10) {
445*57400dccSAndrii Nakryiko 				bpf_repeat(10) {
446*57400dccSAndrii Nakryiko 					bpf_repeat(10) {
447*57400dccSAndrii Nakryiko 						sum += 1;
448*57400dccSAndrii Nakryiko 					}
449*57400dccSAndrii Nakryiko 				}
450*57400dccSAndrii Nakryiko 			}
451*57400dccSAndrii Nakryiko 		}
452*57400dccSAndrii Nakryiko 		/* validate that we can break from inside bpf_repeat() */
453*57400dccSAndrii Nakryiko 		break;
454*57400dccSAndrii Nakryiko 	}
455*57400dccSAndrii Nakryiko 
456*57400dccSAndrii Nakryiko 	return sum;
457*57400dccSAndrii Nakryiko }
458*57400dccSAndrii Nakryiko 
459*57400dccSAndrii Nakryiko static __noinline void fill_inner_dimension(int row)
460*57400dccSAndrii Nakryiko {
461*57400dccSAndrii Nakryiko 	int col;
462*57400dccSAndrii Nakryiko 
463*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
464*57400dccSAndrii Nakryiko 		arr2d[row][col] = row * col;
465*57400dccSAndrii Nakryiko 	}
466*57400dccSAndrii Nakryiko }
467*57400dccSAndrii Nakryiko 
468*57400dccSAndrii Nakryiko static __noinline int sum_inner_dimension(int row)
469*57400dccSAndrii Nakryiko {
470*57400dccSAndrii Nakryiko 	int sum = 0, col;
471*57400dccSAndrii Nakryiko 
472*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
473*57400dccSAndrii Nakryiko 		sum += arr2d[row][col];
474*57400dccSAndrii Nakryiko 		arr2d_row_sums[row] += arr2d[row][col];
475*57400dccSAndrii Nakryiko 		arr2d_col_sums[col] += arr2d[row][col];
476*57400dccSAndrii Nakryiko 	}
477*57400dccSAndrii Nakryiko 
478*57400dccSAndrii Nakryiko 	return sum;
479*57400dccSAndrii Nakryiko }
480*57400dccSAndrii Nakryiko 
481*57400dccSAndrii Nakryiko SEC("raw_tp")
482*57400dccSAndrii Nakryiko __success
483*57400dccSAndrii Nakryiko int iter_subprog_iters(const void *ctx)
484*57400dccSAndrii Nakryiko {
485*57400dccSAndrii Nakryiko 	int sum, row, col;
486*57400dccSAndrii Nakryiko 
487*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
488*57400dccSAndrii Nakryiko 
489*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
490*57400dccSAndrii Nakryiko 		fill_inner_dimension(row);
491*57400dccSAndrii Nakryiko 	}
492*57400dccSAndrii Nakryiko 
493*57400dccSAndrii Nakryiko 	/* zero-initialize sums */
494*57400dccSAndrii Nakryiko 	sum = 0;
495*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
496*57400dccSAndrii Nakryiko 		arr2d_row_sums[row] = 0;
497*57400dccSAndrii Nakryiko 	}
498*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
499*57400dccSAndrii Nakryiko 		arr2d_col_sums[col] = 0;
500*57400dccSAndrii Nakryiko 	}
501*57400dccSAndrii Nakryiko 
502*57400dccSAndrii Nakryiko 	/* calculate sums */
503*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
504*57400dccSAndrii Nakryiko 		sum += sum_inner_dimension(row);
505*57400dccSAndrii Nakryiko 	}
506*57400dccSAndrii Nakryiko 
507*57400dccSAndrii Nakryiko 	bpf_printk("ITER_SUBPROG_ITERS: total sum=%d", sum);
508*57400dccSAndrii Nakryiko 	bpf_for(row, 0, ARRAY_SIZE(arr2d)) {
509*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SUBPROG_ITERS: row #%d sum=%d",
510*57400dccSAndrii Nakryiko 			   row, arr2d_row_sums[row]);
511*57400dccSAndrii Nakryiko 	}
512*57400dccSAndrii Nakryiko 	bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) {
513*57400dccSAndrii Nakryiko 		bpf_printk("ITER_SUBPROG_ITERS: col #%d sum=%d%s",
514*57400dccSAndrii Nakryiko 			   col, arr2d_col_sums[col],
515*57400dccSAndrii Nakryiko 			   col == ARRAY_SIZE(arr2d[0]) - 1 ? "\n" : "");
516*57400dccSAndrii Nakryiko 	}
517*57400dccSAndrii Nakryiko 
518*57400dccSAndrii Nakryiko 	return 0;
519*57400dccSAndrii Nakryiko }
520*57400dccSAndrii Nakryiko 
521*57400dccSAndrii Nakryiko struct {
522*57400dccSAndrii Nakryiko 	__uint(type, BPF_MAP_TYPE_ARRAY);
523*57400dccSAndrii Nakryiko 	__type(key, int);
524*57400dccSAndrii Nakryiko 	__type(value, int);
525*57400dccSAndrii Nakryiko 	__uint(max_entries, 1000);
526*57400dccSAndrii Nakryiko } arr_map SEC(".maps");
527*57400dccSAndrii Nakryiko 
528*57400dccSAndrii Nakryiko SEC("?raw_tp")
529*57400dccSAndrii Nakryiko __failure __msg("invalid mem access 'scalar'")
530*57400dccSAndrii Nakryiko int iter_err_too_permissive1(const void *ctx)
531*57400dccSAndrii Nakryiko {
532*57400dccSAndrii Nakryiko 	int *map_val = NULL;
533*57400dccSAndrii Nakryiko 	int key = 0;
534*57400dccSAndrii Nakryiko 
535*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
536*57400dccSAndrii Nakryiko 
537*57400dccSAndrii Nakryiko 	map_val = bpf_map_lookup_elem(&arr_map, &key);
538*57400dccSAndrii Nakryiko 	if (!map_val)
539*57400dccSAndrii Nakryiko 		return 0;
540*57400dccSAndrii Nakryiko 
541*57400dccSAndrii Nakryiko 	bpf_repeat(1000000) {
542*57400dccSAndrii Nakryiko 		map_val = NULL;
543*57400dccSAndrii Nakryiko 	}
544*57400dccSAndrii Nakryiko 
545*57400dccSAndrii Nakryiko 	*map_val = 123;
546*57400dccSAndrii Nakryiko 
547*57400dccSAndrii Nakryiko 	return 0;
548*57400dccSAndrii Nakryiko }
549*57400dccSAndrii Nakryiko 
550*57400dccSAndrii Nakryiko SEC("?raw_tp")
551*57400dccSAndrii Nakryiko __failure __msg("invalid mem access 'map_value_or_null'")
552*57400dccSAndrii Nakryiko int iter_err_too_permissive2(const void *ctx)
553*57400dccSAndrii Nakryiko {
554*57400dccSAndrii Nakryiko 	int *map_val = NULL;
555*57400dccSAndrii Nakryiko 	int key = 0;
556*57400dccSAndrii Nakryiko 
557*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
558*57400dccSAndrii Nakryiko 
559*57400dccSAndrii Nakryiko 	map_val = bpf_map_lookup_elem(&arr_map, &key);
560*57400dccSAndrii Nakryiko 	if (!map_val)
561*57400dccSAndrii Nakryiko 		return 0;
562*57400dccSAndrii Nakryiko 
563*57400dccSAndrii Nakryiko 	bpf_repeat(1000000) {
564*57400dccSAndrii Nakryiko 		map_val = bpf_map_lookup_elem(&arr_map, &key);
565*57400dccSAndrii Nakryiko 	}
566*57400dccSAndrii Nakryiko 
567*57400dccSAndrii Nakryiko 	*map_val = 123;
568*57400dccSAndrii Nakryiko 
569*57400dccSAndrii Nakryiko 	return 0;
570*57400dccSAndrii Nakryiko }
571*57400dccSAndrii Nakryiko 
572*57400dccSAndrii Nakryiko SEC("?raw_tp")
573*57400dccSAndrii Nakryiko __failure __msg("invalid mem access 'map_value_or_null'")
574*57400dccSAndrii Nakryiko int iter_err_too_permissive3(const void *ctx)
575*57400dccSAndrii Nakryiko {
576*57400dccSAndrii Nakryiko 	int *map_val = NULL;
577*57400dccSAndrii Nakryiko 	int key = 0;
578*57400dccSAndrii Nakryiko 	bool found = false;
579*57400dccSAndrii Nakryiko 
580*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
581*57400dccSAndrii Nakryiko 
582*57400dccSAndrii Nakryiko 	bpf_repeat(1000000) {
583*57400dccSAndrii Nakryiko 		map_val = bpf_map_lookup_elem(&arr_map, &key);
584*57400dccSAndrii Nakryiko 		found = true;
585*57400dccSAndrii Nakryiko 	}
586*57400dccSAndrii Nakryiko 
587*57400dccSAndrii Nakryiko 	if (found)
588*57400dccSAndrii Nakryiko 		*map_val = 123;
589*57400dccSAndrii Nakryiko 
590*57400dccSAndrii Nakryiko 	return 0;
591*57400dccSAndrii Nakryiko }
592*57400dccSAndrii Nakryiko 
593*57400dccSAndrii Nakryiko SEC("raw_tp")
594*57400dccSAndrii Nakryiko __success
595*57400dccSAndrii Nakryiko int iter_tricky_but_fine(const void *ctx)
596*57400dccSAndrii Nakryiko {
597*57400dccSAndrii Nakryiko 	int *map_val = NULL;
598*57400dccSAndrii Nakryiko 	int key = 0;
599*57400dccSAndrii Nakryiko 	bool found = false;
600*57400dccSAndrii Nakryiko 
601*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
602*57400dccSAndrii Nakryiko 
603*57400dccSAndrii Nakryiko 	bpf_repeat(1000000) {
604*57400dccSAndrii Nakryiko 		map_val = bpf_map_lookup_elem(&arr_map, &key);
605*57400dccSAndrii Nakryiko 		if (map_val) {
606*57400dccSAndrii Nakryiko 			found = true;
607*57400dccSAndrii Nakryiko 			break;
608*57400dccSAndrii Nakryiko 		}
609*57400dccSAndrii Nakryiko 	}
610*57400dccSAndrii Nakryiko 
611*57400dccSAndrii Nakryiko 	if (found)
612*57400dccSAndrii Nakryiko 		*map_val = 123;
613*57400dccSAndrii Nakryiko 
614*57400dccSAndrii Nakryiko 	return 0;
615*57400dccSAndrii Nakryiko }
616*57400dccSAndrii Nakryiko 
617*57400dccSAndrii Nakryiko #define __bpf_memzero(p, sz) bpf_probe_read_kernel((p), (sz), 0)
618*57400dccSAndrii Nakryiko 
619*57400dccSAndrii Nakryiko SEC("raw_tp")
620*57400dccSAndrii Nakryiko __success
621*57400dccSAndrii Nakryiko int iter_stack_array_loop(const void *ctx)
622*57400dccSAndrii Nakryiko {
623*57400dccSAndrii Nakryiko 	long arr1[16], arr2[16], sum = 0;
624*57400dccSAndrii Nakryiko 	int *v, i;
625*57400dccSAndrii Nakryiko 
626*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
627*57400dccSAndrii Nakryiko 
628*57400dccSAndrii Nakryiko 	/* zero-init arr1 and arr2 in such a way that verifier doesn't know
629*57400dccSAndrii Nakryiko 	 * it's all zeros; if we don't do that, we'll make BPF verifier track
630*57400dccSAndrii Nakryiko 	 * all combination of zero/non-zero stack slots for arr1/arr2, which
631*57400dccSAndrii Nakryiko 	 * will lead to O(2^(ARRAY_SIZE(arr1)+ARRAY_SIZE(arr2))) different
632*57400dccSAndrii Nakryiko 	 * states
633*57400dccSAndrii Nakryiko 	 */
634*57400dccSAndrii Nakryiko 	__bpf_memzero(arr1, sizeof(arr1));
635*57400dccSAndrii Nakryiko 	__bpf_memzero(arr2, sizeof(arr1));
636*57400dccSAndrii Nakryiko 
637*57400dccSAndrii Nakryiko 	/* validate that we can break and continue when using bpf_for() */
638*57400dccSAndrii Nakryiko 	bpf_for(i, 0, ARRAY_SIZE(arr1)) {
639*57400dccSAndrii Nakryiko 		if (i & 1) {
640*57400dccSAndrii Nakryiko 			arr1[i] = i;
641*57400dccSAndrii Nakryiko 			continue;
642*57400dccSAndrii Nakryiko 		} else {
643*57400dccSAndrii Nakryiko 			arr2[i] = i;
644*57400dccSAndrii Nakryiko 			break;
645*57400dccSAndrii Nakryiko 		}
646*57400dccSAndrii Nakryiko 	}
647*57400dccSAndrii Nakryiko 
648*57400dccSAndrii Nakryiko 	bpf_for(i, 0, ARRAY_SIZE(arr1)) {
649*57400dccSAndrii Nakryiko 		sum += arr1[i] + arr2[i];
650*57400dccSAndrii Nakryiko 	}
651*57400dccSAndrii Nakryiko 
652*57400dccSAndrii Nakryiko 	return sum;
653*57400dccSAndrii Nakryiko }
654*57400dccSAndrii Nakryiko 
655*57400dccSAndrii Nakryiko static __noinline void fill(struct bpf_iter_num *it, int *arr, __u32 n, int mul)
656*57400dccSAndrii Nakryiko {
657*57400dccSAndrii Nakryiko 	int *t, i;
658*57400dccSAndrii Nakryiko 
659*57400dccSAndrii Nakryiko 	while ((t = bpf_iter_num_next(it))) {
660*57400dccSAndrii Nakryiko 		i = *t;
661*57400dccSAndrii Nakryiko 		if (i >= n)
662*57400dccSAndrii Nakryiko 			break;
663*57400dccSAndrii Nakryiko 		arr[i] =  i * mul;
664*57400dccSAndrii Nakryiko 	}
665*57400dccSAndrii Nakryiko }
666*57400dccSAndrii Nakryiko 
667*57400dccSAndrii Nakryiko static __noinline int sum(struct bpf_iter_num *it, int *arr, __u32 n)
668*57400dccSAndrii Nakryiko {
669*57400dccSAndrii Nakryiko 	int *t, i, sum = 0;;
670*57400dccSAndrii Nakryiko 
671*57400dccSAndrii Nakryiko 	while ((t = bpf_iter_num_next(it))) {
672*57400dccSAndrii Nakryiko 		i = *t;
673*57400dccSAndrii Nakryiko 		if (i >= n)
674*57400dccSAndrii Nakryiko 			break;
675*57400dccSAndrii Nakryiko 		sum += arr[i];
676*57400dccSAndrii Nakryiko 	}
677*57400dccSAndrii Nakryiko 
678*57400dccSAndrii Nakryiko 	return sum;
679*57400dccSAndrii Nakryiko }
680*57400dccSAndrii Nakryiko 
681*57400dccSAndrii Nakryiko SEC("raw_tp")
682*57400dccSAndrii Nakryiko __success
683*57400dccSAndrii Nakryiko int iter_pass_iter_ptr_to_subprog(const void *ctx)
684*57400dccSAndrii Nakryiko {
685*57400dccSAndrii Nakryiko 	int arr1[16], arr2[32];
686*57400dccSAndrii Nakryiko 	struct bpf_iter_num it;
687*57400dccSAndrii Nakryiko 	int n, sum1, sum2;
688*57400dccSAndrii Nakryiko 
689*57400dccSAndrii Nakryiko 	MY_PID_GUARD();
690*57400dccSAndrii Nakryiko 
691*57400dccSAndrii Nakryiko 	/* fill arr1 */
692*57400dccSAndrii Nakryiko 	n = ARRAY_SIZE(arr1);
693*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, n);
694*57400dccSAndrii Nakryiko 	fill(&it, arr1, n, 2);
695*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
696*57400dccSAndrii Nakryiko 
697*57400dccSAndrii Nakryiko 	/* fill arr2 */
698*57400dccSAndrii Nakryiko 	n = ARRAY_SIZE(arr2);
699*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, n);
700*57400dccSAndrii Nakryiko 	fill(&it, arr2, n, 10);
701*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
702*57400dccSAndrii Nakryiko 
703*57400dccSAndrii Nakryiko 	/* sum arr1 */
704*57400dccSAndrii Nakryiko 	n = ARRAY_SIZE(arr1);
705*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, n);
706*57400dccSAndrii Nakryiko 	sum1 = sum(&it, arr1, n);
707*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
708*57400dccSAndrii Nakryiko 
709*57400dccSAndrii Nakryiko 	/* sum arr2 */
710*57400dccSAndrii Nakryiko 	n = ARRAY_SIZE(arr2);
711*57400dccSAndrii Nakryiko 	bpf_iter_num_new(&it, 0, n);
712*57400dccSAndrii Nakryiko 	sum2 = sum(&it, arr2, n);
713*57400dccSAndrii Nakryiko 	bpf_iter_num_destroy(&it);
714*57400dccSAndrii Nakryiko 
715*57400dccSAndrii Nakryiko 	bpf_printk("sum1=%d, sum2=%d", sum1, sum2);
716*57400dccSAndrii Nakryiko 
717*57400dccSAndrii Nakryiko 	return 0;
718*57400dccSAndrii Nakryiko }
719*57400dccSAndrii Nakryiko 
720*57400dccSAndrii Nakryiko char _license[] SEC("license") = "GPL";
721