File Index
Files and directories
Sign in
FILE

iters_looping.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/iters_looping.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
  3
  4#include <errno.h>
  5#include <string.h>
  6#include <linux/bpf.h>
  7#include <bpf/bpf_helpers.h>
  8#include "bpf_misc.h"
  9
 10char _license[] SEC("license") = "GPL";
 11
 12#define ITER_HELPERS						\
 13	  __imm(bpf_iter_num_new),				\
 14	  __imm(bpf_iter_num_next),				\
 15	  __imm(bpf_iter_num_destroy)
 16
 17SEC("?raw_tp")
 18__success
 19int force_clang_to_emit_btf_for_externs(void *ctx)
 20{
 21	/* we need this as a workaround to enforce compiler emitting BTF
 22	 * information for bpf_iter_num_{new,next,destroy}() kfuncs,
 23	 * as, apparently, it doesn't emit it for symbols only referenced from
 24	 * assembly (or cleanup attribute, for that matter, as well)
 25	 */
 26	bpf_repeat(0);
 27
 28	return 0;
 29}
 30
 31SEC("?raw_tp")
 32__success
 33int consume_first_item_only(void *ctx)
 34{
 35	struct bpf_iter_num iter;
 36
 37	asm volatile (
 38		/* create iterator */
 39		"r1 = %[iter];"
 40		"r2 = 0;"
 41		"r3 = 1000;"
 42		"call %[bpf_iter_num_new];"
 43
 44		/* consume first item */
 45		"r1 = %[iter];"
 46		"call %[bpf_iter_num_next];"
 47
 48		"if r0 == 0 goto +1;"
 49		"r0 = *(u32 *)(r0 + 0);"
 50
 51		/* destroy iterator */
 52		"r1 = %[iter];"
 53		"call %[bpf_iter_num_destroy];"
 54		:
 55		: __imm_ptr(iter), ITER_HELPERS
 56		: __clobber_common
 57	);
 58
 59	return 0;
 60}
 61
 62SEC("?raw_tp")
 63__failure __msg("R0 invalid mem access 'scalar'")
 64int missing_null_check_fail(void *ctx)
 65{
 66	struct bpf_iter_num iter;
 67
 68	asm volatile (
 69		/* create iterator */
 70		"r1 = %[iter];"
 71		"r2 = 0;"
 72		"r3 = 1000;"
 73		"call %[bpf_iter_num_new];"
 74
 75		/* consume first element */
 76		"r1 = %[iter];"
 77		"call %[bpf_iter_num_next];"
 78
 79		/* FAIL: deref with no NULL check */
 80		"r1 = *(u32 *)(r0 + 0);"
 81
 82		/* destroy iterator */
 83		"r1 = %[iter];"
 84		"call %[bpf_iter_num_destroy];"
 85		:
 86		: __imm_ptr(iter), ITER_HELPERS
 87		: __clobber_common
 88	);
 89
 90	return 0;
 91}
 92
 93SEC("?raw_tp")
 94__failure
 95__msg("invalid access to memory, mem_size=4 off=0 size=8")
 96__msg("R0 min value is outside of the allowed memory range")
 97int wrong_sized_read_fail(void *ctx)
 98{
 99	struct bpf_iter_num iter;
100
101	asm volatile (
102		/* create iterator */
103		"r1 = %[iter];"
104		"r2 = 0;"
105		"r3 = 1000;"
106		"call %[bpf_iter_num_new];"
107
108		/* consume first element */
109		"r1 = %[iter];"
110		"call %[bpf_iter_num_next];"
111
112		"if r0 == 0 goto +1;"
113		/* FAIL: deref more than available 4 bytes */
114		"r0 = *(u64 *)(r0 + 0);"
115
116		/* destroy iterator */
117		"r1 = %[iter];"
118		"call %[bpf_iter_num_destroy];"
119		:
120		: __imm_ptr(iter), ITER_HELPERS
121		: __clobber_common
122	);
123
124	return 0;
125}
126
127SEC("?raw_tp")
128__success __log_level(2)
129__flag(BPF_F_TEST_STATE_FREQ)
130int simplest_loop(void *ctx)
131{
132	struct bpf_iter_num iter;
133
134	asm volatile (
135		"r6 = 0;" /* init sum */
136
137		/* create iterator */
138		"r1 = %[iter];"
139		"r2 = 0;"
140		"r3 = 10;"
141		"call %[bpf_iter_num_new];"
142
143	"1:"
144		/* consume next item */
145		"r1 = %[iter];"
146		"call %[bpf_iter_num_next];"
147
148		"if r0 == 0 goto 2f;"
149		"r0 = *(u32 *)(r0 + 0);"
150		"r6 += r0;" /* accumulate sum */
151		"goto 1b;"
152
153	"2:"
154		/* destroy iterator */
155		"r1 = %[iter];"
156		"call %[bpf_iter_num_destroy];"
157		:
158		: __imm_ptr(iter), ITER_HELPERS
159		: __clobber_common, "r6"
160	);
161
162	return 0;
163}
164
165__used
166static void iterator_with_diff_stack_depth(int x)
167{
168	struct bpf_iter_num iter;
169
170	asm volatile (
171		"if r1 == 42 goto 0f;"
172		"*(u64 *)(r10 - 128) = 0;"
173	"0:"
174		/* create iterator */
175		"r1 = %[iter];"
176		"r2 = 0;"
177		"r3 = 10;"
178		"call %[bpf_iter_num_new];"
179	"1:"
180		/* consume next item */
181		"r1 = %[iter];"
182		"call %[bpf_iter_num_next];"
183		"if r0 == 0 goto 2f;"
184		"goto 1b;"
185	"2:"
186		/* destroy iterator */
187		"r1 = %[iter];"
188		"call %[bpf_iter_num_destroy];"
189		:
190		: __imm_ptr(iter), ITER_HELPERS
191		: __clobber_common, "r6"
192	);
193}
194
195SEC("socket")
196__success
197__naked int widening_stack_size_bug(void *ctx)
198{
199	/*
200	 * Depending on iterator_with_diff_stack_depth() parameter value,
201	 * subprogram stack depth is either 8 or 128 bytes. Arrange values so
202	 * that it is 128 on a first call and 8 on a second. This triggered a
203	 * bug in verifier's widen_imprecise_scalars() logic.
204	 */
205	asm volatile (
206		"r6 = 0;"
207		"r1 = 0;"
208	"1:"
209		"call iterator_with_diff_stack_depth;"
210		"r1 = 42;"
211		"r6 += 1;"
212		"if r6 < 2 goto 1b;"
213		"r0 = 0;"
214		"exit;"
215		::: __clobber_all);
216}
~/ Read-only file preview.