Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/* Converted from tools/testing/selftests/bpf/verifier/regalloc.c */
  3
  4#include <linux/bpf.h>
  5#include <bpf/bpf_helpers.h>
  6#include "bpf_misc.h"
  7
  8#define MAX_ENTRIES 11
  9
 10struct test_val {
 11	unsigned int index;
 12	int foo[MAX_ENTRIES];
 13};
 14
 15struct {
 16	__uint(type, BPF_MAP_TYPE_HASH);
 17	__uint(max_entries, 1);
 18	__type(key, long long);
 19	__type(value, struct test_val);
 20} map_hash_48b SEC(".maps");
 21
 22SEC("tracepoint")
 23__description("regalloc basic")
 24__success __flag(BPF_F_ANY_ALIGNMENT)
 25__naked void regalloc_basic(void)
 26{
 27	asm volatile ("					\
 28	r6 = r1;					\
 29	r1 = 0;						\
 30	*(u64*)(r10 - 8) = r1;				\
 31	r2 = r10;					\
 32	r2 += -8;					\
 33	r1 = %[map_hash_48b] ll;			\
 34	call %[bpf_map_lookup_elem];			\
 35	if r0 == 0 goto l0_%=;				\
 36	r7 = r0;					\
 37	call %[bpf_get_prandom_u32];			\
 38	r2 = r0;					\
 39	if r0 s> 20 goto l0_%=;				\
 40	if r2 s< 0 goto l0_%=;				\
 41	r7 += r0;					\
 42	r7 += r2;					\
 43	r0 = *(u64*)(r7 + 0);				\
 44l0_%=:	exit;						\
 45"	:
 46	: __imm(bpf_get_prandom_u32),
 47	  __imm(bpf_map_lookup_elem),
 48	  __imm_addr(map_hash_48b)
 49	: __clobber_all);
 50}
 51
 52SEC("tracepoint")
 53__description("regalloc negative")
 54__failure __msg("invalid access to map value, value_size=48 off=48 size=1")
 55__naked void regalloc_negative(void)
 56{
 57	asm volatile ("					\
 58	r6 = r1;					\
 59	r1 = 0;						\
 60	*(u64*)(r10 - 8) = r1;				\
 61	r2 = r10;					\
 62	r2 += -8;					\
 63	r1 = %[map_hash_48b] ll;			\
 64	call %[bpf_map_lookup_elem];			\
 65	if r0 == 0 goto l0_%=;				\
 66	r7 = r0;					\
 67	call %[bpf_get_prandom_u32];			\
 68	r2 = r0;					\
 69	if r0 s> 24 goto l0_%=;				\
 70	if r2 s< 0 goto l0_%=;				\
 71	r7 += r0;					\
 72	r7 += r2;					\
 73	r0 = *(u8*)(r7 + 0);				\
 74l0_%=:	exit;						\
 75"	:
 76	: __imm(bpf_get_prandom_u32),
 77	  __imm(bpf_map_lookup_elem),
 78	  __imm_addr(map_hash_48b)
 79	: __clobber_all);
 80}
 81
 82SEC("tracepoint")
 83__description("regalloc src_reg mark")
 84__success __flag(BPF_F_ANY_ALIGNMENT)
 85__naked void regalloc_src_reg_mark(void)
 86{
 87	asm volatile ("					\
 88	r6 = r1;					\
 89	r1 = 0;						\
 90	*(u64*)(r10 - 8) = r1;				\
 91	r2 = r10;					\
 92	r2 += -8;					\
 93	r1 = %[map_hash_48b] ll;			\
 94	call %[bpf_map_lookup_elem];			\
 95	if r0 == 0 goto l0_%=;				\
 96	r7 = r0;					\
 97	call %[bpf_get_prandom_u32];			\
 98	r2 = r0;					\
 99	if r0 s> 20 goto l0_%=;				\
100	r3 = 0;						\
101	if r3 s>= r2 goto l0_%=;			\
102	r7 += r0;					\
103	r7 += r2;					\
104	r0 = *(u64*)(r7 + 0);				\
105l0_%=:	exit;						\
106"	:
107	: __imm(bpf_get_prandom_u32),
108	  __imm(bpf_map_lookup_elem),
109	  __imm_addr(map_hash_48b)
110	: __clobber_all);
111}
112
113SEC("tracepoint")
114__description("regalloc src_reg negative")
115__failure __msg("invalid access to map value, value_size=48 off=44 size=8")
116__flag(BPF_F_ANY_ALIGNMENT)
117__naked void regalloc_src_reg_negative(void)
118{
119	asm volatile ("					\
120	r6 = r1;					\
121	r1 = 0;						\
122	*(u64*)(r10 - 8) = r1;				\
123	r2 = r10;					\
124	r2 += -8;					\
125	r1 = %[map_hash_48b] ll;			\
126	call %[bpf_map_lookup_elem];			\
127	if r0 == 0 goto l0_%=;				\
128	r7 = r0;					\
129	call %[bpf_get_prandom_u32];			\
130	r2 = r0;					\
131	if r0 s> 22 goto l0_%=;				\
132	r3 = 0;						\
133	if r3 s>= r2 goto l0_%=;			\
134	r7 += r0;					\
135	r7 += r2;					\
136	r0 = *(u64*)(r7 + 0);				\
137l0_%=:	exit;						\
138"	:
139	: __imm(bpf_get_prandom_u32),
140	  __imm(bpf_map_lookup_elem),
141	  __imm_addr(map_hash_48b)
142	: __clobber_all);
143}
144
145SEC("tracepoint")
146__description("regalloc and spill")
147__success __flag(BPF_F_ANY_ALIGNMENT)
148__naked void regalloc_and_spill(void)
149{
150	asm volatile ("					\
151	r6 = r1;					\
152	r1 = 0;						\
153	*(u64*)(r10 - 8) = r1;				\
154	r2 = r10;					\
155	r2 += -8;					\
156	r1 = %[map_hash_48b] ll;			\
157	call %[bpf_map_lookup_elem];			\
158	if r0 == 0 goto l0_%=;				\
159	r7 = r0;					\
160	call %[bpf_get_prandom_u32];			\
161	r2 = r0;					\
162	if r0 s> 20 goto l0_%=;				\
163	/* r0 has upper bound that should propagate into r2 */\
164	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
165	r0 = 0;						\
166	r2 = 0;				/* clear r0 and r2 */\
167	r3 = *(u64*)(r10 - 8);		/* fill r3 */	\
168	if r0 s>= r3 goto l0_%=;			\
169	/* r3 has lower and upper bounds */		\
170	r7 += r3;					\
171	r0 = *(u64*)(r7 + 0);				\
172l0_%=:	exit;						\
173"	:
174	: __imm(bpf_get_prandom_u32),
175	  __imm(bpf_map_lookup_elem),
176	  __imm_addr(map_hash_48b)
177	: __clobber_all);
178}
179
180SEC("tracepoint")
181__description("regalloc and spill negative")
182__failure __msg("invalid access to map value, value_size=48 off=48 size=8")
183__flag(BPF_F_ANY_ALIGNMENT)
184__naked void regalloc_and_spill_negative(void)
185{
186	asm volatile ("					\
187	r6 = r1;					\
188	r1 = 0;						\
189	*(u64*)(r10 - 8) = r1;				\
190	r2 = r10;					\
191	r2 += -8;					\
192	r1 = %[map_hash_48b] ll;			\
193	call %[bpf_map_lookup_elem];			\
194	if r0 == 0 goto l0_%=;				\
195	r7 = r0;					\
196	call %[bpf_get_prandom_u32];			\
197	r2 = r0;					\
198	if r0 s> 48 goto l0_%=;				\
199	/* r0 has upper bound that should propagate into r2 */\
200	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
201	r0 = 0;						\
202	r2 = 0;				/* clear r0 and r2 */\
203	r3 = *(u64*)(r10 - 8);		/* fill r3 */\
204	if r0 s>= r3 goto l0_%=;			\
205	/* r3 has lower and upper bounds */		\
206	r7 += r3;					\
207	r0 = *(u64*)(r7 + 0);				\
208l0_%=:	exit;						\
209"	:
210	: __imm(bpf_get_prandom_u32),
211	  __imm(bpf_map_lookup_elem),
212	  __imm_addr(map_hash_48b)
213	: __clobber_all);
214}
215
216SEC("tracepoint")
217__description("regalloc three regs")
218__success __flag(BPF_F_ANY_ALIGNMENT)
219__naked void regalloc_three_regs(void)
220{
221	asm volatile ("					\
222	r6 = r1;					\
223	r1 = 0;						\
224	*(u64*)(r10 - 8) = r1;				\
225	r2 = r10;					\
226	r2 += -8;					\
227	r1 = %[map_hash_48b] ll;			\
228	call %[bpf_map_lookup_elem];			\
229	if r0 == 0 goto l0_%=;				\
230	r7 = r0;					\
231	call %[bpf_get_prandom_u32];			\
232	r2 = r0;					\
233	r4 = r2;					\
234	if r0 s> 12 goto l0_%=;				\
235	if r2 s< 0 goto l0_%=;				\
236	r7 += r0;					\
237	r7 += r2;					\
238	r7 += r4;					\
239	r0 = *(u64*)(r7 + 0);				\
240l0_%=:	exit;						\
241"	:
242	: __imm(bpf_get_prandom_u32),
243	  __imm(bpf_map_lookup_elem),
244	  __imm_addr(map_hash_48b)
245	: __clobber_all);
246}
247
248SEC("tracepoint")
249__description("regalloc after call")
250__success __flag(BPF_F_ANY_ALIGNMENT)
251__naked void regalloc_after_call(void)
252{
253	asm volatile ("					\
254	r6 = r1;					\
255	r1 = 0;						\
256	*(u64*)(r10 - 8) = r1;				\
257	r2 = r10;					\
258	r2 += -8;					\
259	r1 = %[map_hash_48b] ll;			\
260	call %[bpf_map_lookup_elem];			\
261	if r0 == 0 goto l0_%=;				\
262	r7 = r0;					\
263	call %[bpf_get_prandom_u32];			\
264	r8 = r0;					\
265	r9 = r0;					\
266	call regalloc_after_call__1;			\
267	if r8 s> 20 goto l0_%=;				\
268	if r9 s< 0 goto l0_%=;				\
269	r7 += r8;					\
270	r7 += r9;					\
271	r0 = *(u64*)(r7 + 0);				\
272l0_%=:	exit;						\
273"	:
274	: __imm(bpf_get_prandom_u32),
275	  __imm(bpf_map_lookup_elem),
276	  __imm_addr(map_hash_48b)
277	: __clobber_all);
278}
279
280static __naked __noinline __attribute__((used))
281void regalloc_after_call__1(void)
282{
283	asm volatile ("					\
284	r0 = 0;						\
285	exit;						\
286"	::: __clobber_all);
287}
288
289SEC("tracepoint")
290__description("regalloc in callee")
291__success __flag(BPF_F_ANY_ALIGNMENT)
292__naked void regalloc_in_callee(void)
293{
294	asm volatile ("					\
295	r6 = r1;					\
296	r1 = 0;						\
297	*(u64*)(r10 - 8) = r1;				\
298	r2 = r10;					\
299	r2 += -8;					\
300	r1 = %[map_hash_48b] ll;			\
301	call %[bpf_map_lookup_elem];			\
302	if r0 == 0 goto l0_%=;				\
303	r7 = r0;					\
304	call %[bpf_get_prandom_u32];			\
305	r1 = r0;					\
306	r2 = r0;					\
307	r3 = r7;					\
308	call regalloc_in_callee__1;			\
309l0_%=:	exit;						\
310"	:
311	: __imm(bpf_get_prandom_u32),
312	  __imm(bpf_map_lookup_elem),
313	  __imm_addr(map_hash_48b)
314	: __clobber_all);
315}
316
317static __naked __noinline __attribute__((used))
318void regalloc_in_callee__1(void)
319{
320	asm volatile ("					\
321	if r1 s> 20 goto l0_%=;				\
322	if r2 s< 0 goto l0_%=;				\
323	r3 += r1;					\
324	r3 += r2;					\
325	r0 = *(u64*)(r3 + 0);				\
326	exit;						\
327l0_%=:	r0 = 0;						\
328	exit;						\
329"	::: __clobber_all);
330}
331
332SEC("tracepoint")
333__description("regalloc, spill, JEQ")
334__success
335__naked void regalloc_spill_jeq(void)
336{
337	asm volatile ("					\
338	r6 = r1;					\
339	r1 = 0;						\
340	*(u64*)(r10 - 8) = r1;				\
341	r2 = r10;					\
342	r2 += -8;					\
343	r1 = %[map_hash_48b] ll;			\
344	call %[bpf_map_lookup_elem];			\
345	*(u64*)(r10 - 8) = r0;		/* spill r0 */	\
346	if r0 == 0 goto l0_%=;				\
347l0_%=:	/* The verifier will walk the rest twice with r0 == 0 and r0 == map_value */\
348	call %[bpf_get_prandom_u32];			\
349	r2 = r0;					\
350	if r2 == 20 goto l1_%=;				\
351l1_%=:	/* The verifier will walk the rest two more times with r0 == 20 and r0 == unknown */\
352	r3 = *(u64*)(r10 - 8);		/* fill r3 with map_value */\
353	if r3 == 0 goto l2_%=;		/* skip ldx if map_value == NULL */\
354	/* Buggy verifier will think that r3 == 20 here */\
355	r0 = *(u64*)(r3 + 0);		/* read from map_value */\
356l2_%=:	exit;						\
357"	:
358	: __imm(bpf_get_prandom_u32),
359	  __imm(bpf_map_lookup_elem),
360	  __imm_addr(map_hash_48b)
361	: __clobber_all);
362}
363
364char _license[] SEC("license") = "GPL";
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/* Converted from tools/testing/selftests/bpf/verifier/regalloc.c */
  3
  4#include <linux/bpf.h>
  5#include <bpf/bpf_helpers.h>
  6#include "bpf_misc.h"
  7
  8#define MAX_ENTRIES 11
  9
 10struct test_val {
 11	unsigned int index;
 12	int foo[MAX_ENTRIES];
 13};
 14
 15struct {
 16	__uint(type, BPF_MAP_TYPE_HASH);
 17	__uint(max_entries, 1);
 18	__type(key, long long);
 19	__type(value, struct test_val);
 20} map_hash_48b SEC(".maps");
 21
 22SEC("tracepoint")
 23__description("regalloc basic")
 24__success __flag(BPF_F_ANY_ALIGNMENT)
 25__naked void regalloc_basic(void)
 26{
 27	asm volatile ("					\
 28	r6 = r1;					\
 29	r1 = 0;						\
 30	*(u64*)(r10 - 8) = r1;				\
 31	r2 = r10;					\
 32	r2 += -8;					\
 33	r1 = %[map_hash_48b] ll;			\
 34	call %[bpf_map_lookup_elem];			\
 35	if r0 == 0 goto l0_%=;				\
 36	r7 = r0;					\
 37	call %[bpf_get_prandom_u32];			\
 38	r2 = r0;					\
 39	if r0 s> 20 goto l0_%=;				\
 40	if r2 s< 0 goto l0_%=;				\
 41	r7 += r0;					\
 42	r7 += r2;					\
 43	r0 = *(u64*)(r7 + 0);				\
 44l0_%=:	exit;						\
 45"	:
 46	: __imm(bpf_get_prandom_u32),
 47	  __imm(bpf_map_lookup_elem),
 48	  __imm_addr(map_hash_48b)
 49	: __clobber_all);
 50}
 51
 52SEC("tracepoint")
 53__description("regalloc negative")
 54__failure __msg("invalid access to map value, value_size=48 off=48 size=1")
 55__naked void regalloc_negative(void)
 56{
 57	asm volatile ("					\
 58	r6 = r1;					\
 59	r1 = 0;						\
 60	*(u64*)(r10 - 8) = r1;				\
 61	r2 = r10;					\
 62	r2 += -8;					\
 63	r1 = %[map_hash_48b] ll;			\
 64	call %[bpf_map_lookup_elem];			\
 65	if r0 == 0 goto l0_%=;				\
 66	r7 = r0;					\
 67	call %[bpf_get_prandom_u32];			\
 68	r2 = r0;					\
 69	if r0 s> 24 goto l0_%=;				\
 70	if r2 s< 0 goto l0_%=;				\
 71	r7 += r0;					\
 72	r7 += r2;					\
 73	r0 = *(u8*)(r7 + 0);				\
 74l0_%=:	exit;						\
 75"	:
 76	: __imm(bpf_get_prandom_u32),
 77	  __imm(bpf_map_lookup_elem),
 78	  __imm_addr(map_hash_48b)
 79	: __clobber_all);
 80}
 81
 82SEC("tracepoint")
 83__description("regalloc src_reg mark")
 84__success __flag(BPF_F_ANY_ALIGNMENT)
 85__naked void regalloc_src_reg_mark(void)
 86{
 87	asm volatile ("					\
 88	r6 = r1;					\
 89	r1 = 0;						\
 90	*(u64*)(r10 - 8) = r1;				\
 91	r2 = r10;					\
 92	r2 += -8;					\
 93	r1 = %[map_hash_48b] ll;			\
 94	call %[bpf_map_lookup_elem];			\
 95	if r0 == 0 goto l0_%=;				\
 96	r7 = r0;					\
 97	call %[bpf_get_prandom_u32];			\
 98	r2 = r0;					\
 99	if r0 s> 20 goto l0_%=;				\
100	r3 = 0;						\
101	if r3 s>= r2 goto l0_%=;			\
102	r7 += r0;					\
103	r7 += r2;					\
104	r0 = *(u64*)(r7 + 0);				\
105l0_%=:	exit;						\
106"	:
107	: __imm(bpf_get_prandom_u32),
108	  __imm(bpf_map_lookup_elem),
109	  __imm_addr(map_hash_48b)
110	: __clobber_all);
111}
112
113SEC("tracepoint")
114__description("regalloc src_reg negative")
115__failure __msg("invalid access to map value, value_size=48 off=44 size=8")
116__flag(BPF_F_ANY_ALIGNMENT)
117__naked void regalloc_src_reg_negative(void)
118{
119	asm volatile ("					\
120	r6 = r1;					\
121	r1 = 0;						\
122	*(u64*)(r10 - 8) = r1;				\
123	r2 = r10;					\
124	r2 += -8;					\
125	r1 = %[map_hash_48b] ll;			\
126	call %[bpf_map_lookup_elem];			\
127	if r0 == 0 goto l0_%=;				\
128	r7 = r0;					\
129	call %[bpf_get_prandom_u32];			\
130	r2 = r0;					\
131	if r0 s> 22 goto l0_%=;				\
132	r3 = 0;						\
133	if r3 s>= r2 goto l0_%=;			\
134	r7 += r0;					\
135	r7 += r2;					\
136	r0 = *(u64*)(r7 + 0);				\
137l0_%=:	exit;						\
138"	:
139	: __imm(bpf_get_prandom_u32),
140	  __imm(bpf_map_lookup_elem),
141	  __imm_addr(map_hash_48b)
142	: __clobber_all);
143}
144
145SEC("tracepoint")
146__description("regalloc and spill")
147__success __flag(BPF_F_ANY_ALIGNMENT)
148__naked void regalloc_and_spill(void)
149{
150	asm volatile ("					\
151	r6 = r1;					\
152	r1 = 0;						\
153	*(u64*)(r10 - 8) = r1;				\
154	r2 = r10;					\
155	r2 += -8;					\
156	r1 = %[map_hash_48b] ll;			\
157	call %[bpf_map_lookup_elem];			\
158	if r0 == 0 goto l0_%=;				\
159	r7 = r0;					\
160	call %[bpf_get_prandom_u32];			\
161	r2 = r0;					\
162	if r0 s> 20 goto l0_%=;				\
163	/* r0 has upper bound that should propagate into r2 */\
164	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
165	r0 = 0;						\
166	r2 = 0;				/* clear r0 and r2 */\
167	r3 = *(u64*)(r10 - 8);		/* fill r3 */	\
168	if r0 s>= r3 goto l0_%=;			\
169	/* r3 has lower and upper bounds */		\
170	r7 += r3;					\
171	r0 = *(u64*)(r7 + 0);				\
172l0_%=:	exit;						\
173"	:
174	: __imm(bpf_get_prandom_u32),
175	  __imm(bpf_map_lookup_elem),
176	  __imm_addr(map_hash_48b)
177	: __clobber_all);
178}
179
180SEC("tracepoint")
181__description("regalloc and spill negative")
182__failure __msg("invalid access to map value, value_size=48 off=48 size=8")
183__flag(BPF_F_ANY_ALIGNMENT)
184__naked void regalloc_and_spill_negative(void)
185{
186	asm volatile ("					\
187	r6 = r1;					\
188	r1 = 0;						\
189	*(u64*)(r10 - 8) = r1;				\
190	r2 = r10;					\
191	r2 += -8;					\
192	r1 = %[map_hash_48b] ll;			\
193	call %[bpf_map_lookup_elem];			\
194	if r0 == 0 goto l0_%=;				\
195	r7 = r0;					\
196	call %[bpf_get_prandom_u32];			\
197	r2 = r0;					\
198	if r0 s> 48 goto l0_%=;				\
199	/* r0 has upper bound that should propagate into r2 */\
200	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\
201	r0 = 0;						\
202	r2 = 0;				/* clear r0 and r2 */\
203	r3 = *(u64*)(r10 - 8);		/* fill r3 */\
204	if r0 s>= r3 goto l0_%=;			\
205	/* r3 has lower and upper bounds */		\
206	r7 += r3;					\
207	r0 = *(u64*)(r7 + 0);				\
208l0_%=:	exit;						\
209"	:
210	: __imm(bpf_get_prandom_u32),
211	  __imm(bpf_map_lookup_elem),
212	  __imm_addr(map_hash_48b)
213	: __clobber_all);
214}
215
216SEC("tracepoint")
217__description("regalloc three regs")
218__success __flag(BPF_F_ANY_ALIGNMENT)
219__naked void regalloc_three_regs(void)
220{
221	asm volatile ("					\
222	r6 = r1;					\
223	r1 = 0;						\
224	*(u64*)(r10 - 8) = r1;				\
225	r2 = r10;					\
226	r2 += -8;					\
227	r1 = %[map_hash_48b] ll;			\
228	call %[bpf_map_lookup_elem];			\
229	if r0 == 0 goto l0_%=;				\
230	r7 = r0;					\
231	call %[bpf_get_prandom_u32];			\
232	r2 = r0;					\
233	r4 = r2;					\
234	if r0 s> 12 goto l0_%=;				\
235	if r2 s< 0 goto l0_%=;				\
236	r7 += r0;					\
237	r7 += r2;					\
238	r7 += r4;					\
239	r0 = *(u64*)(r7 + 0);				\
240l0_%=:	exit;						\
241"	:
242	: __imm(bpf_get_prandom_u32),
243	  __imm(bpf_map_lookup_elem),
244	  __imm_addr(map_hash_48b)
245	: __clobber_all);
246}
247
248SEC("tracepoint")
249__description("regalloc after call")
250__success __flag(BPF_F_ANY_ALIGNMENT)
251__naked void regalloc_after_call(void)
252{
253	asm volatile ("					\
254	r6 = r1;					\
255	r1 = 0;						\
256	*(u64*)(r10 - 8) = r1;				\
257	r2 = r10;					\
258	r2 += -8;					\
259	r1 = %[map_hash_48b] ll;			\
260	call %[bpf_map_lookup_elem];			\
261	if r0 == 0 goto l0_%=;				\
262	r7 = r0;					\
263	call %[bpf_get_prandom_u32];			\
264	r8 = r0;					\
265	r9 = r0;					\
266	call regalloc_after_call__1;			\
267	if r8 s> 20 goto l0_%=;				\
268	if r9 s< 0 goto l0_%=;				\
269	r7 += r8;					\
270	r7 += r9;					\
271	r0 = *(u64*)(r7 + 0);				\
272l0_%=:	exit;						\
273"	:
274	: __imm(bpf_get_prandom_u32),
275	  __imm(bpf_map_lookup_elem),
276	  __imm_addr(map_hash_48b)
277	: __clobber_all);
278}
279
280static __naked __noinline __attribute__((used))
281void regalloc_after_call__1(void)
282{
283	asm volatile ("					\
284	r0 = 0;						\
285	exit;						\
286"	::: __clobber_all);
287}
288
289SEC("tracepoint")
290__description("regalloc in callee")
291__success __flag(BPF_F_ANY_ALIGNMENT)
292__naked void regalloc_in_callee(void)
293{
294	asm volatile ("					\
295	r6 = r1;					\
296	r1 = 0;						\
297	*(u64*)(r10 - 8) = r1;				\
298	r2 = r10;					\
299	r2 += -8;					\
300	r1 = %[map_hash_48b] ll;			\
301	call %[bpf_map_lookup_elem];			\
302	if r0 == 0 goto l0_%=;				\
303	r7 = r0;					\
304	call %[bpf_get_prandom_u32];			\
305	r1 = r0;					\
306	r2 = r0;					\
307	r3 = r7;					\
308	call regalloc_in_callee__1;			\
309l0_%=:	exit;						\
310"	:
311	: __imm(bpf_get_prandom_u32),
312	  __imm(bpf_map_lookup_elem),
313	  __imm_addr(map_hash_48b)
314	: __clobber_all);
315}
316
317static __naked __noinline __attribute__((used))
318void regalloc_in_callee__1(void)
319{
320	asm volatile ("					\
321	if r1 s> 20 goto l0_%=;				\
322	if r2 s< 0 goto l0_%=;				\
323	r3 += r1;					\
324	r3 += r2;					\
325	r0 = *(u64*)(r3 + 0);				\
326	exit;						\
327l0_%=:	r0 = 0;						\
328	exit;						\
329"	::: __clobber_all);
330}
331
332SEC("tracepoint")
333__description("regalloc, spill, JEQ")
334__success
335__naked void regalloc_spill_jeq(void)
336{
337	asm volatile ("					\
338	r6 = r1;					\
339	r1 = 0;						\
340	*(u64*)(r10 - 8) = r1;				\
341	r2 = r10;					\
342	r2 += -8;					\
343	r1 = %[map_hash_48b] ll;			\
344	call %[bpf_map_lookup_elem];			\
345	*(u64*)(r10 - 8) = r0;		/* spill r0 */	\
346	if r0 == 0 goto l0_%=;				\
347l0_%=:	/* The verifier will walk the rest twice with r0 == 0 and r0 == map_value */\
348	call %[bpf_get_prandom_u32];			\
349	r2 = r0;					\
350	if r2 == 20 goto l1_%=;				\
351l1_%=:	/* The verifier will walk the rest two more times with r0 == 20 and r0 == unknown */\
352	r3 = *(u64*)(r10 - 8);		/* fill r3 with map_value */\
353	if r3 == 0 goto l2_%=;		/* skip ldx if map_value == NULL */\
354	/* Buggy verifier will think that r3 == 20 here */\
355	r0 = *(u64*)(r3 + 0);		/* read from map_value */\
356l2_%=:	exit;						\
357"	:
358	: __imm(bpf_get_prandom_u32),
359	  __imm(bpf_map_lookup_elem),
360	  __imm_addr(map_hash_48b)
361	: __clobber_all);
362}
363
364char _license[] SEC("license") = "GPL";