1// SPDX-License-Identifier: GPL-2.0
2/* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */
3
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include <errno.h>
7#include "bpf_misc.h"
8
9#define MAX_ENTRIES 11
10
11struct test_val {
12	unsigned int index;
13	int foo[MAX_ENTRIES];
14};
15
16struct {
17	__uint(type, BPF_MAP_TYPE_ARRAY);
18	__uint(max_entries, 1);
19	__type(key, int);
20	__type(value, struct test_val);
21} map_array_48b SEC(".maps");
22
23struct other_val {
24	long long foo;
25	long long bar;
26};
27
28struct {
29	__uint(type, BPF_MAP_TYPE_HASH);
30	__uint(max_entries, 1);
31	__type(key, long long);
32	__type(value, struct other_val);
33} map_hash_16b SEC(".maps");
34
35struct {
36	__uint(type, BPF_MAP_TYPE_HASH);
37	__uint(max_entries, 1);
38	__type(key, long long);
39	__type(value, struct test_val);
40} map_hash_48b SEC(".maps");
41
42SEC("socket")
43__description("map access: known scalar += value_ptr unknown vs const")
44__success __failure_unpriv
45__msg_unpriv("R1 tried to add from different maps, paths or scalars")
46__retval(1)
47__naked void value_ptr_unknown_vs_const(void)
48{
49	asm volatile ("					\
50	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
51	r1 = 0;						\
52	*(u64*)(r10 - 8) = r1;				\
53	r2 = r10;					\
54	r2 += -8;					\
55	if r0 == 1 goto l0_%=;				\
56	r1 = %[map_hash_16b] ll;			\
57	if r0 != 1 goto l1_%=;				\
58l0_%=:	r1 = %[map_array_48b] ll;			\
59l1_%=:	call %[bpf_map_lookup_elem];			\
60	if r0 == 0 goto l2_%=;				\
61	r4 = *(u8*)(r0 + 0);				\
62	if r4 == 1 goto l3_%=;				\
63	r1 = 6;						\
64	r1 = -r1;					\
65	r1 &= 0x7;					\
66	goto l4_%=;					\
67l3_%=:	r1 = 3;						\
68l4_%=:	r1 += r0;					\
69	r0 = *(u8*)(r1 + 0);				\
70l2_%=:	r0 = 1;						\
71	exit;						\
72"	:
73	: __imm(bpf_map_lookup_elem),
74	  __imm_addr(map_array_48b),
75	  __imm_addr(map_hash_16b),
76	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
77	: __clobber_all);
78}
79
80SEC("socket")
81__description("map access: known scalar += value_ptr const vs unknown")
82__success __failure_unpriv
83__msg_unpriv("R1 tried to add from different maps, paths or scalars")
84__retval(1)
85__naked void value_ptr_const_vs_unknown(void)
86{
87	asm volatile ("					\
88	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
89	r1 = 0;						\
90	*(u64*)(r10 - 8) = r1;				\
91	r2 = r10;					\
92	r2 += -8;					\
93	if r0 == 1 goto l0_%=;				\
94	r1 = %[map_hash_16b] ll;			\
95	if r0 != 1 goto l1_%=;				\
96l0_%=:	r1 = %[map_array_48b] ll;			\
97l1_%=:	call %[bpf_map_lookup_elem];			\
98	if r0 == 0 goto l2_%=;				\
99	r4 = *(u8*)(r0 + 0);				\
100	if r4 == 1 goto l3_%=;				\
101	r1 = 3;						\
102	goto l4_%=;					\
103l3_%=:	r1 = 6;						\
104	r1 = -r1;					\
105	r1 &= 0x7;					\
106l4_%=:	r1 += r0;					\
107	r0 = *(u8*)(r1 + 0);				\
108l2_%=:	r0 = 1;						\
109	exit;						\
110"	:
111	: __imm(bpf_map_lookup_elem),
112	  __imm_addr(map_array_48b),
113	  __imm_addr(map_hash_16b),
114	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
115	: __clobber_all);
116}
117
118SEC("socket")
119__description("map access: known scalar += value_ptr const vs const (ne)")
120__success __failure_unpriv
121__msg_unpriv("R1 tried to add from different maps, paths or scalars")
122__retval(1)
123__naked void ptr_const_vs_const_ne(void)
124{
125	asm volatile ("					\
126	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
127	r1 = 0;						\
128	*(u64*)(r10 - 8) = r1;				\
129	r2 = r10;					\
130	r2 += -8;					\
131	if r0 == 1 goto l0_%=;				\
132	r1 = %[map_hash_16b] ll;			\
133	if r0 != 1 goto l1_%=;				\
134l0_%=:	r1 = %[map_array_48b] ll;			\
135l1_%=:	call %[bpf_map_lookup_elem];			\
136	if r0 == 0 goto l2_%=;				\
137	r4 = *(u8*)(r0 + 0);				\
138	if r4 == 1 goto l3_%=;				\
139	r1 = 3;						\
140	goto l4_%=;					\
141l3_%=:	r1 = 5;						\
142l4_%=:	r1 += r0;					\
143	r0 = *(u8*)(r1 + 0);				\
144l2_%=:	r0 = 1;						\
145	exit;						\
146"	:
147	: __imm(bpf_map_lookup_elem),
148	  __imm_addr(map_array_48b),
149	  __imm_addr(map_hash_16b),
150	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
151	: __clobber_all);
152}
153
154SEC("socket")
155__description("map access: known scalar += value_ptr const vs const (eq)")
156__success __success_unpriv __retval(1)
157__naked void ptr_const_vs_const_eq(void)
158{
159	asm volatile ("					\
160	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
161	r1 = 0;						\
162	*(u64*)(r10 - 8) = r1;				\
163	r2 = r10;					\
164	r2 += -8;					\
165	if r0 == 1 goto l0_%=;				\
166	r1 = %[map_hash_16b] ll;			\
167	if r0 != 1 goto l1_%=;				\
168l0_%=:	r1 = %[map_array_48b] ll;			\
169l1_%=:	call %[bpf_map_lookup_elem];			\
170	if r0 == 0 goto l2_%=;				\
171	r4 = *(u8*)(r0 + 0);				\
172	if r4 == 1 goto l3_%=;				\
173	r1 = 5;						\
174	goto l4_%=;					\
175l3_%=:	r1 = 5;						\
176l4_%=:	r1 += r0;					\
177	r0 = *(u8*)(r1 + 0);				\
178l2_%=:	r0 = 1;						\
179	exit;						\
180"	:
181	: __imm(bpf_map_lookup_elem),
182	  __imm_addr(map_array_48b),
183	  __imm_addr(map_hash_16b),
184	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
185	: __clobber_all);
186}
187
188SEC("socket")
189__description("map access: known scalar += value_ptr unknown vs unknown (eq)")
190__success __success_unpriv __retval(1)
191__naked void ptr_unknown_vs_unknown_eq(void)
192{
193	asm volatile ("					\
194	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
195	r1 = 0;						\
196	*(u64*)(r10 - 8) = r1;				\
197	r2 = r10;					\
198	r2 += -8;					\
199	if r0 == 1 goto l0_%=;				\
200	r1 = %[map_hash_16b] ll;			\
201	if r0 != 1 goto l1_%=;				\
202l0_%=:	r1 = %[map_array_48b] ll;			\
203l1_%=:	call %[bpf_map_lookup_elem];			\
204	if r0 == 0 goto l2_%=;				\
205	r4 = *(u8*)(r0 + 0);				\
206	if r4 == 1 goto l3_%=;				\
207	r1 = 6;						\
208	r1 = -r1;					\
209	r1 &= 0x7;					\
210	goto l4_%=;					\
211l3_%=:	r1 = 6;						\
212	r1 = -r1;					\
213	r1 &= 0x7;					\
214l4_%=:	r1 += r0;					\
215	r0 = *(u8*)(r1 + 0);				\
216l2_%=:	r0 = 1;						\
217	exit;						\
218"	:
219	: __imm(bpf_map_lookup_elem),
220	  __imm_addr(map_array_48b),
221	  __imm_addr(map_hash_16b),
222	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
223	: __clobber_all);
224}
225
226SEC("socket")
227__description("map access: known scalar += value_ptr unknown vs unknown (lt)")
228__success __failure_unpriv
229__msg_unpriv("R1 tried to add from different maps, paths or scalars")
230__retval(1)
231__naked void ptr_unknown_vs_unknown_lt(void)
232{
233	asm volatile ("					\
234	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
235	r1 = 0;						\
236	*(u64*)(r10 - 8) = r1;				\
237	r2 = r10;					\
238	r2 += -8;					\
239	if r0 == 1 goto l0_%=;				\
240	r1 = %[map_hash_16b] ll;			\
241	if r0 != 1 goto l1_%=;				\
242l0_%=:	r1 = %[map_array_48b] ll;			\
243l1_%=:	call %[bpf_map_lookup_elem];			\
244	if r0 == 0 goto l2_%=;				\
245	r4 = *(u8*)(r0 + 0);				\
246	if r4 == 1 goto l3_%=;				\
247	r1 = 6;						\
248	r1 = -r1;					\
249	r1 &= 0x3;					\
250	goto l4_%=;					\
251l3_%=:	r1 = 6;						\
252	r1 = -r1;					\
253	r1 &= 0x7;					\
254l4_%=:	r1 += r0;					\
255	r0 = *(u8*)(r1 + 0);				\
256l2_%=:	r0 = 1;						\
257	exit;						\
258"	:
259	: __imm(bpf_map_lookup_elem),
260	  __imm_addr(map_array_48b),
261	  __imm_addr(map_hash_16b),
262	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
263	: __clobber_all);
264}
265
266SEC("socket")
267__description("map access: known scalar += value_ptr unknown vs unknown (gt)")
268__success __failure_unpriv
269__msg_unpriv("R1 tried to add from different maps, paths or scalars")
270__retval(1)
271__naked void ptr_unknown_vs_unknown_gt(void)
272{
273	asm volatile ("					\
274	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
275	r1 = 0;						\
276	*(u64*)(r10 - 8) = r1;				\
277	r2 = r10;					\
278	r2 += -8;					\
279	if r0 == 1 goto l0_%=;				\
280	r1 = %[map_hash_16b] ll;			\
281	if r0 != 1 goto l1_%=;				\
282l0_%=:	r1 = %[map_array_48b] ll;			\
283l1_%=:	call %[bpf_map_lookup_elem];			\
284	if r0 == 0 goto l2_%=;				\
285	r4 = *(u8*)(r0 + 0);				\
286	if r4 == 1 goto l3_%=;				\
287	r1 = 6;						\
288	r1 = -r1;					\
289	r1 &= 0x7;					\
290	goto l4_%=;					\
291l3_%=:	r1 = 6;						\
292	r1 = -r1;					\
293	r1 &= 0x3;					\
294l4_%=:	r1 += r0;					\
295	r0 = *(u8*)(r1 + 0);				\
296l2_%=:	r0 = 1;						\
297	exit;						\
298"	:
299	: __imm(bpf_map_lookup_elem),
300	  __imm_addr(map_array_48b),
301	  __imm_addr(map_hash_16b),
302	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
303	: __clobber_all);
304}
305
306SEC("socket")
307__description("map access: known scalar += value_ptr from different maps")
308__success __success_unpriv __retval(1)
309__naked void value_ptr_from_different_maps(void)
310{
311	asm volatile ("					\
312	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
313	r1 = 0;						\
314	*(u64*)(r10 - 8) = r1;				\
315	r2 = r10;					\
316	r2 += -8;					\
317	if r0 == 1 goto l0_%=;				\
318	r1 = %[map_hash_16b] ll;			\
319	if r0 != 1 goto l1_%=;				\
320l0_%=:	r1 = %[map_array_48b] ll;			\
321l1_%=:	call %[bpf_map_lookup_elem];			\
322	if r0 == 0 goto l2_%=;				\
323	r1 = 4;						\
324	r1 += r0;					\
325	r0 = *(u8*)(r1 + 0);				\
326l2_%=:	r0 = 1;						\
327	exit;						\
328"	:
329	: __imm(bpf_map_lookup_elem),
330	  __imm_addr(map_array_48b),
331	  __imm_addr(map_hash_16b),
332	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
333	: __clobber_all);
334}
335
336SEC("socket")
337__description("map access: value_ptr -= known scalar from different maps")
338__success __failure_unpriv
339__msg_unpriv("R0 min value is outside of the allowed memory range")
340__retval(1)
341__naked void known_scalar_from_different_maps(void)
342{
343	asm volatile ("					\
344	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
345	r1 = 0;						\
346	*(u64*)(r10 - 8) = r1;				\
347	r2 = r10;					\
348	r2 += -8;					\
349	if r0 == 1 goto l0_%=;				\
350	r1 = %[map_hash_16b] ll;			\
351	if r0 != 1 goto l1_%=;				\
352l0_%=:	r1 = %[map_array_48b] ll;			\
353l1_%=:	call %[bpf_map_lookup_elem];			\
354	if r0 == 0 goto l2_%=;				\
355	r1 = 4;						\
356	r0 -= r1;					\
357	r0 += r1;					\
358	r0 = *(u8*)(r0 + 0);				\
359l2_%=:	r0 = 1;						\
360	exit;						\
361"	:
362	: __imm(bpf_map_lookup_elem),
363	  __imm_addr(map_array_48b),
364	  __imm_addr(map_hash_16b),
365	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
366	: __clobber_all);
367}
368
369SEC("socket")
370__description("map access: known scalar += value_ptr from different maps, but same value properties")
371__success __success_unpriv __retval(1)
372__naked void maps_but_same_value_properties(void)
373{
374	asm volatile ("					\
375	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
376	r1 = 0;						\
377	*(u64*)(r10 - 8) = r1;				\
378	r2 = r10;					\
379	r2 += -8;					\
380	if r0 == 1 goto l0_%=;				\
381	r1 = %[map_hash_48b] ll;			\
382	if r0 != 1 goto l1_%=;				\
383l0_%=:	r1 = %[map_array_48b] ll;			\
384l1_%=:	call %[bpf_map_lookup_elem];			\
385	if r0 == 0 goto l2_%=;				\
386	r1 = 4;						\
387	r1 += r0;					\
388	r0 = *(u8*)(r1 + 0);				\
389l2_%=:	r0 = 1;						\
390	exit;						\
391"	:
392	: __imm(bpf_map_lookup_elem),
393	  __imm_addr(map_array_48b),
394	  __imm_addr(map_hash_48b),
395	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
396	: __clobber_all);
397}
398
399SEC("socket")
400__description("map access: mixing value pointer and scalar, 1")
401__success __failure_unpriv __msg_unpriv("R2 pointer comparison prohibited")
402__retval(0)
403__naked void value_pointer_and_scalar_1(void)
404{
405	asm volatile ("					\
406	/* load map value pointer into r0 and r2 */	\
407	r0 = 1;						\
408	r1 = %[map_array_48b] ll;			\
409	r2 = r10;					\
410	r2 += -16;					\
411	r6 = 0;						\
412	*(u64*)(r10 - 16) = r6;				\
413	call %[bpf_map_lookup_elem];			\
414	if r0 != 0 goto l0_%=;				\
415	exit;						\
416l0_%=:	/* load some number from the map into r1 */	\
417	r1 = *(u8*)(r0 + 0);				\
418	/* depending on r1, branch: */			\
419	if r1 != 0 goto l1_%=;				\
420	/* branch A */					\
421	r2 = r0;					\
422	r3 = 0;						\
423	goto l2_%=;					\
424l1_%=:	/* branch B */					\
425	r2 = 0;						\
426	r3 = 0x100000;					\
427l2_%=:	/* common instruction */			\
428	r2 += r3;					\
429	/* depending on r1, branch: */			\
430	if r1 != 0 goto l3_%=;				\
431	/* branch A */					\
432	goto l4_%=;					\
433l3_%=:	/* branch B */					\
434	r0 = 0x13371337;				\
435	/* verifier follows fall-through */		\
436	if r2 != 0x100000 goto l4_%=;			\
437	r0 = 0;						\
438	exit;						\
439l4_%=:	/* fake-dead code; targeted from branch A to	\
440	 * prevent dead code sanitization		\
441	 */						\
442	r0 = *(u8*)(r0 + 0);				\
443	r0 = 0;						\
444	exit;						\
445"	:
446	: __imm(bpf_map_lookup_elem),
447	  __imm_addr(map_array_48b)
448	: __clobber_all);
449}
450
451SEC("socket")
452__description("map access: mixing value pointer and scalar, 2")
453__success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
454__retval(0)
455__naked void value_pointer_and_scalar_2(void)
456{
457	asm volatile ("					\
458	/* load map value pointer into r0 and r2 */	\
459	r0 = 1;						\
460	r1 = %[map_array_48b] ll;			\
461	r2 = r10;					\
462	r2 += -16;					\
463	r6 = 0;						\
464	*(u64*)(r10 - 16) = r6;				\
465	call %[bpf_map_lookup_elem];			\
466	if r0 != 0 goto l0_%=;				\
467	exit;						\
468l0_%=:	/* load some number from the map into r1 */	\
469	r1 = *(u8*)(r0 + 0);				\
470	/* depending on r1, branch: */			\
471	if r1 == 0 goto l1_%=;				\
472	/* branch A */					\
473	r2 = 0;						\
474	r3 = 0x100000;					\
475	goto l2_%=;					\
476l1_%=:	/* branch B */					\
477	r2 = r0;					\
478	r3 = 0;						\
479l2_%=:	/* common instruction */			\
480	r2 += r3;					\
481	/* depending on r1, branch: */			\
482	if r1 != 0 goto l3_%=;				\
483	/* branch A */					\
484	goto l4_%=;					\
485l3_%=:	/* branch B */					\
486	r0 = 0x13371337;				\
487	/* verifier follows fall-through */		\
488	if r2 != 0x100000 goto l4_%=;			\
489	r0 = 0;						\
490	exit;						\
491l4_%=:	/* fake-dead code; targeted from branch A to	\
492	 * prevent dead code sanitization, rejected	\
493	 * via branch B however				\
494	 */						\
495	r0 = *(u8*)(r0 + 0);				\
496	r0 = 0;						\
497	exit;						\
498"	:
499	: __imm(bpf_map_lookup_elem),
500	  __imm_addr(map_array_48b)
501	: __clobber_all);
502}
503
504SEC("socket")
505__description("sanitation: alu with different scalars 1")
506__success __success_unpriv __retval(0x100000)
507__naked void alu_with_different_scalars_1(void)
508{
509	asm volatile ("					\
510	r0 = 1;						\
511	r1 = %[map_array_48b] ll;			\
512	r2 = r10;					\
513	r2 += -16;					\
514	r6 = 0;						\
515	*(u64*)(r10 - 16) = r6;				\
516	call %[bpf_map_lookup_elem];			\
517	if r0 != 0 goto l0_%=;				\
518	exit;						\
519l0_%=:	r1 = *(u32*)(r0 + 0);				\
520	if r1 == 0 goto l1_%=;				\
521	r2 = 0;						\
522	r3 = 0x100000;					\
523	goto l2_%=;					\
524l1_%=:	r2 = 42;					\
525	r3 = 0x100001;					\
526l2_%=:	r2 += r3;					\
527	r0 = r2;					\
528	exit;						\
529"	:
530	: __imm(bpf_map_lookup_elem),
531	  __imm_addr(map_array_48b)
532	: __clobber_all);
533}
534
535SEC("socket")
536__description("sanitation: alu with different scalars 2")
537__success __success_unpriv __retval(0)
538__naked void alu_with_different_scalars_2(void)
539{
540	asm volatile ("					\
541	r0 = 1;						\
542	r1 = %[map_array_48b] ll;			\
543	r6 = r1;					\
544	r2 = r10;					\
545	r2 += -16;					\
546	r7 = 0;						\
547	*(u64*)(r10 - 16) = r7;				\
548	call %[bpf_map_delete_elem];			\
549	r7 = r0;					\
550	r1 = r6;					\
551	r2 = r10;					\
552	r2 += -16;					\
553	call %[bpf_map_delete_elem];			\
554	r6 = r0;					\
555	r8 = r6;					\
556	r8 += r7;					\
557	r0 = r8;					\
558	r0 += %[einval];				\
559	r0 += %[einval];				\
560	exit;						\
561"	:
562	: __imm(bpf_map_delete_elem),
563	  __imm_addr(map_array_48b),
564	  __imm_const(einval, EINVAL)
565	: __clobber_all);
566}
567
568SEC("socket")
569__description("sanitation: alu with different scalars 3")
570__success __success_unpriv __retval(0)
571__naked void alu_with_different_scalars_3(void)
572{
573	asm volatile ("					\
574	r0 = %[einval];					\
575	r0 *= -1;					\
576	r7 = r0;					\
577	r0 = %[einval];					\
578	r0 *= -1;					\
579	r6 = r0;					\
580	r8 = r6;					\
581	r8 += r7;					\
582	r0 = r8;					\
583	r0 += %[einval];				\
584	r0 += %[einval];				\
585	exit;						\
586"	:
587	: __imm_const(einval, EINVAL)
588	: __clobber_all);
589}
590
591SEC("socket")
592__description("map access: value_ptr += known scalar, upper oob arith, test 1")
593__success __failure_unpriv
594__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
595__retval(1)
596__naked void upper_oob_arith_test_1(void)
597{
598	asm volatile ("					\
599	r1 = 0;						\
600	*(u64*)(r10 - 8) = r1;				\
601	r2 = r10;					\
602	r2 += -8;					\
603	r1 = %[map_array_48b] ll;			\
604	call %[bpf_map_lookup_elem];			\
605	if r0 == 0 goto l0_%=;				\
606	r1 = 48;					\
607	r0 += r1;					\
608	r0 -= r1;					\
609	r0 = *(u8*)(r0 + 0);				\
610l0_%=:	r0 = 1;						\
611	exit;						\
612"	:
613	: __imm(bpf_map_lookup_elem),
614	  __imm_addr(map_array_48b)
615	: __clobber_all);
616}
617
618SEC("socket")
619__description("map access: value_ptr += known scalar, upper oob arith, test 2")
620__success __failure_unpriv
621__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
622__retval(1)
623__naked void upper_oob_arith_test_2(void)
624{
625	asm volatile ("					\
626	r1 = 0;						\
627	*(u64*)(r10 - 8) = r1;				\
628	r2 = r10;					\
629	r2 += -8;					\
630	r1 = %[map_array_48b] ll;			\
631	call %[bpf_map_lookup_elem];			\
632	if r0 == 0 goto l0_%=;				\
633	r1 = 49;					\
634	r0 += r1;					\
635	r0 -= r1;					\
636	r0 = *(u8*)(r0 + 0);				\
637l0_%=:	r0 = 1;						\
638	exit;						\
639"	:
640	: __imm(bpf_map_lookup_elem),
641	  __imm_addr(map_array_48b)
642	: __clobber_all);
643}
644
645SEC("socket")
646__description("map access: value_ptr += known scalar, upper oob arith, test 3")
647__success __success_unpriv __retval(1)
648__naked void upper_oob_arith_test_3(void)
649{
650	asm volatile ("					\
651	r1 = 0;						\
652	*(u64*)(r10 - 8) = r1;				\
653	r2 = r10;					\
654	r2 += -8;					\
655	r1 = %[map_array_48b] ll;			\
656	call %[bpf_map_lookup_elem];			\
657	if r0 == 0 goto l0_%=;				\
658	r1 = 47;					\
659	r0 += r1;					\
660	r0 -= r1;					\
661	r0 = *(u8*)(r0 + 0);				\
662l0_%=:	r0 = 1;						\
663	exit;						\
664"	:
665	: __imm(bpf_map_lookup_elem),
666	  __imm_addr(map_array_48b)
667	: __clobber_all);
668}
669
670SEC("socket")
671__description("map access: value_ptr -= known scalar, lower oob arith, test 1")
672__failure __msg("R0 min value is outside of the allowed memory range")
673__failure_unpriv
674__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
675__naked void lower_oob_arith_test_1(void)
676{
677	asm volatile ("					\
678	r1 = 0;						\
679	*(u64*)(r10 - 8) = r1;				\
680	r2 = r10;					\
681	r2 += -8;					\
682	r1 = %[map_array_48b] ll;			\
683	call %[bpf_map_lookup_elem];			\
684	if r0 == 0 goto l0_%=;				\
685	r1 = 47;					\
686	r0 += r1;					\
687	r1 = 48;					\
688	r0 -= r1;					\
689	r0 = *(u8*)(r0 + 0);				\
690l0_%=:	r0 = 1;						\
691	exit;						\
692"	:
693	: __imm(bpf_map_lookup_elem),
694	  __imm_addr(map_array_48b)
695	: __clobber_all);
696}
697
698SEC("socket")
699__description("map access: value_ptr -= known scalar, lower oob arith, test 2")
700__success __failure_unpriv
701__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
702__retval(1)
703__naked void lower_oob_arith_test_2(void)
704{
705	asm volatile ("					\
706	r1 = 0;						\
707	*(u64*)(r10 - 8) = r1;				\
708	r2 = r10;					\
709	r2 += -8;					\
710	r1 = %[map_array_48b] ll;			\
711	call %[bpf_map_lookup_elem];			\
712	if r0 == 0 goto l0_%=;				\
713	r1 = 47;					\
714	r0 += r1;					\
715	r1 = 48;					\
716	r0 -= r1;					\
717	r1 = 1;						\
718	r0 += r1;					\
719	r0 = *(u8*)(r0 + 0);				\
720l0_%=:	r0 = 1;						\
721	exit;						\
722"	:
723	: __imm(bpf_map_lookup_elem),
724	  __imm_addr(map_array_48b)
725	: __clobber_all);
726}
727
728SEC("socket")
729__description("map access: value_ptr -= known scalar, lower oob arith, test 3")
730__success __success_unpriv __retval(1)
731__naked void lower_oob_arith_test_3(void)
732{
733	asm volatile ("					\
734	r1 = 0;						\
735	*(u64*)(r10 - 8) = r1;				\
736	r2 = r10;					\
737	r2 += -8;					\
738	r1 = %[map_array_48b] ll;			\
739	call %[bpf_map_lookup_elem];			\
740	if r0 == 0 goto l0_%=;				\
741	r1 = 47;					\
742	r0 += r1;					\
743	r1 = 47;					\
744	r0 -= r1;					\
745	r0 = *(u8*)(r0 + 0);				\
746l0_%=:	r0 = 1;						\
747	exit;						\
748"	:
749	: __imm(bpf_map_lookup_elem),
750	  __imm_addr(map_array_48b)
751	: __clobber_all);
752}
753
754SEC("socket")
755__description("map access: known scalar += value_ptr")
756__success __success_unpriv __retval(1)
757__naked void access_known_scalar_value_ptr_1(void)
758{
759	asm volatile ("					\
760	r1 = 0;						\
761	*(u64*)(r10 - 8) = r1;				\
762	r2 = r10;					\
763	r2 += -8;					\
764	r1 = %[map_array_48b] ll;			\
765	call %[bpf_map_lookup_elem];			\
766	if r0 == 0 goto l0_%=;				\
767	r1 = 4;						\
768	r1 += r0;					\
769	r0 = *(u8*)(r1 + 0);				\
770l0_%=:	r0 = 1;						\
771	exit;						\
772"	:
773	: __imm(bpf_map_lookup_elem),
774	  __imm_addr(map_array_48b)
775	: __clobber_all);
776}
777
778SEC("socket")
779__description("map access: value_ptr += known scalar, 1")
780__success __success_unpriv __retval(1)
781__naked void value_ptr_known_scalar_1(void)
782{
783	asm volatile ("					\
784	r1 = 0;						\
785	*(u64*)(r10 - 8) = r1;				\
786	r2 = r10;					\
787	r2 += -8;					\
788	r1 = %[map_array_48b] ll;			\
789	call %[bpf_map_lookup_elem];			\
790	if r0 == 0 goto l0_%=;				\
791	r1 = 4;						\
792	r0 += r1;					\
793	r1 = *(u8*)(r0 + 0);				\
794l0_%=:	r0 = 1;						\
795	exit;						\
796"	:
797	: __imm(bpf_map_lookup_elem),
798	  __imm_addr(map_array_48b)
799	: __clobber_all);
800}
801
802SEC("socket")
803__description("map access: value_ptr += known scalar, 2")
804__failure __msg("invalid access to map value")
805__failure_unpriv
806__naked void value_ptr_known_scalar_2_1(void)
807{
808	asm volatile ("					\
809	r1 = 0;						\
810	*(u64*)(r10 - 8) = r1;				\
811	r2 = r10;					\
812	r2 += -8;					\
813	r1 = %[map_array_48b] ll;			\
814	call %[bpf_map_lookup_elem];			\
815	if r0 == 0 goto l0_%=;				\
816	r1 = 49;					\
817	r0 += r1;					\
818	r1 = *(u8*)(r0 + 0);				\
819l0_%=:	r0 = 1;						\
820	exit;						\
821"	:
822	: __imm(bpf_map_lookup_elem),
823	  __imm_addr(map_array_48b)
824	: __clobber_all);
825}
826
827SEC("socket")
828__description("map access: value_ptr += known scalar, 3")
829__failure __msg("invalid access to map value")
830__failure_unpriv
831__naked void value_ptr_known_scalar_3(void)
832{
833	asm volatile ("					\
834	r1 = 0;						\
835	*(u64*)(r10 - 8) = r1;				\
836	r2 = r10;					\
837	r2 += -8;					\
838	r1 = %[map_array_48b] ll;			\
839	call %[bpf_map_lookup_elem];			\
840	if r0 == 0 goto l0_%=;				\
841	r1 = -1;					\
842	r0 += r1;					\
843	r1 = *(u8*)(r0 + 0);				\
844l0_%=:	r0 = 1;						\
845	exit;						\
846"	:
847	: __imm(bpf_map_lookup_elem),
848	  __imm_addr(map_array_48b)
849	: __clobber_all);
850}
851
852SEC("socket")
853__description("map access: value_ptr += known scalar, 4")
854__success __success_unpriv __retval(1)
855__naked void value_ptr_known_scalar_4(void)
856{
857	asm volatile ("					\
858	r1 = 0;						\
859	*(u64*)(r10 - 8) = r1;				\
860	r2 = r10;					\
861	r2 += -8;					\
862	r1 = %[map_array_48b] ll;			\
863	call %[bpf_map_lookup_elem];			\
864	if r0 == 0 goto l0_%=;				\
865	r1 = 5;						\
866	r0 += r1;					\
867	r1 = -2;					\
868	r0 += r1;					\
869	r1 = -1;					\
870	r0 += r1;					\
871	r1 = *(u8*)(r0 + 0);				\
872l0_%=:	r0 = 1;						\
873	exit;						\
874"	:
875	: __imm(bpf_map_lookup_elem),
876	  __imm_addr(map_array_48b)
877	: __clobber_all);
878}
879
880SEC("socket")
881__description("map access: value_ptr += known scalar, 5")
882__success __success_unpriv __retval(0xabcdef12)
883__naked void value_ptr_known_scalar_5(void)
884{
885	asm volatile ("					\
886	r1 = 0;						\
887	*(u64*)(r10 - 8) = r1;				\
888	r2 = r10;					\
889	r2 += -8;					\
890	r1 = %[map_array_48b] ll;			\
891	call %[bpf_map_lookup_elem];			\
892	if r0 == 0 goto l0_%=;				\
893	r1 = %[__imm_0];				\
894	r1 += r0;					\
895	r0 = *(u32*)(r1 + 0);				\
896l0_%=:	exit;						\
897"	:
898	: __imm(bpf_map_lookup_elem),
899	  __imm_addr(map_array_48b),
900	  __imm_const(__imm_0, (6 + 1) * sizeof(int))
901	: __clobber_all);
902}
903
904SEC("socket")
905__description("map access: value_ptr += known scalar, 6")
906__success __success_unpriv __retval(0xabcdef12)
907__naked void value_ptr_known_scalar_6(void)
908{
909	asm volatile ("					\
910	r1 = 0;						\
911	*(u64*)(r10 - 8) = r1;				\
912	r2 = r10;					\
913	r2 += -8;					\
914	r1 = %[map_array_48b] ll;			\
915	call %[bpf_map_lookup_elem];			\
916	if r0 == 0 goto l0_%=;				\
917	r1 = %[__imm_0];				\
918	r0 += r1;					\
919	r1 = %[__imm_1];				\
920	r0 += r1;					\
921	r0 = *(u32*)(r0 + 0);				\
922l0_%=:	exit;						\
923"	:
924	: __imm(bpf_map_lookup_elem),
925	  __imm_addr(map_array_48b),
926	  __imm_const(__imm_0, (3 + 1) * sizeof(int)),
927	  __imm_const(__imm_1, 3 * sizeof(int))
928	: __clobber_all);
929}
930
931SEC("socket")
932__description("map access: value_ptr += N, value_ptr -= N known scalar")
933__success __success_unpriv __retval(0x12345678)
934__naked void value_ptr_n_known_scalar(void)
935{
936	asm volatile ("					\
937	r1 = 0;						\
938	*(u64*)(r10 - 8) = r1;				\
939	r2 = r10;					\
940	r2 += -8;					\
941	r1 = %[map_array_48b] ll;			\
942	call %[bpf_map_lookup_elem];			\
943	if r0 == 0 goto l0_%=;				\
944	w1 = 0x12345678;				\
945	*(u32*)(r0 + 0) = r1;				\
946	r0 += 2;					\
947	r1 = 2;						\
948	r0 -= r1;					\
949	r0 = *(u32*)(r0 + 0);				\
950l0_%=:	exit;						\
951"	:
952	: __imm(bpf_map_lookup_elem),
953	  __imm_addr(map_array_48b)
954	: __clobber_all);
955}
956
957SEC("socket")
958__description("map access: unknown scalar += value_ptr, 1")
959__success __success_unpriv __retval(1)
960__naked void unknown_scalar_value_ptr_1(void)
961{
962	asm volatile ("					\
963	r1 = 0;						\
964	*(u64*)(r10 - 8) = r1;				\
965	r2 = r10;					\
966	r2 += -8;					\
967	r1 = %[map_array_48b] ll;			\
968	call %[bpf_map_lookup_elem];			\
969	if r0 == 0 goto l0_%=;				\
970	r1 = *(u8*)(r0 + 0);				\
971	r1 &= 0xf;					\
972	r1 += r0;					\
973	r0 = *(u8*)(r1 + 0);				\
974l0_%=:	r0 = 1;						\
975	exit;						\
976"	:
977	: __imm(bpf_map_lookup_elem),
978	  __imm_addr(map_array_48b)
979	: __clobber_all);
980}
981
982SEC("socket")
983__description("map access: unknown scalar += value_ptr, 2")
984__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
985__naked void unknown_scalar_value_ptr_2(void)
986{
987	asm volatile ("					\
988	r1 = 0;						\
989	*(u64*)(r10 - 8) = r1;				\
990	r2 = r10;					\
991	r2 += -8;					\
992	r1 = %[map_array_48b] ll;			\
993	call %[bpf_map_lookup_elem];			\
994	if r0 == 0 goto l0_%=;				\
995	r1 = *(u32*)(r0 + 0);				\
996	r1 &= 31;					\
997	r1 += r0;					\
998	r0 = *(u32*)(r1 + 0);				\
999l0_%=:	exit;						\
1000"	:
1001	: __imm(bpf_map_lookup_elem),
1002	  __imm_addr(map_array_48b)
1003	: __clobber_all);
1004}
1005
1006SEC("socket")
1007__description("map access: unknown scalar += value_ptr, 3")
1008__success __failure_unpriv
1009__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
1010__retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1011__naked void unknown_scalar_value_ptr_3(void)
1012{
1013	asm volatile ("					\
1014	r1 = 0;						\
1015	*(u64*)(r10 - 8) = r1;				\
1016	r2 = r10;					\
1017	r2 += -8;					\
1018	r1 = %[map_array_48b] ll;			\
1019	call %[bpf_map_lookup_elem];			\
1020	if r0 == 0 goto l0_%=;				\
1021	r1 = -1;					\
1022	r0 += r1;					\
1023	r1 = 1;						\
1024	r0 += r1;					\
1025	r1 = *(u32*)(r0 + 0);				\
1026	r1 &= 31;					\
1027	r1 += r0;					\
1028	r0 = *(u32*)(r1 + 0);				\
1029l0_%=:	exit;						\
1030"	:
1031	: __imm(bpf_map_lookup_elem),
1032	  __imm_addr(map_array_48b)
1033	: __clobber_all);
1034}
1035
1036SEC("socket")
1037__description("map access: unknown scalar += value_ptr, 4")
1038__failure __msg("R1 max value is outside of the allowed memory range")
1039__msg_unpriv("R1 pointer arithmetic of map value goes out of range")
1040__flag(BPF_F_ANY_ALIGNMENT)
1041__naked void unknown_scalar_value_ptr_4(void)
1042{
1043	asm volatile ("					\
1044	r1 = 0;						\
1045	*(u64*)(r10 - 8) = r1;				\
1046	r2 = r10;					\
1047	r2 += -8;					\
1048	r1 = %[map_array_48b] ll;			\
1049	call %[bpf_map_lookup_elem];			\
1050	if r0 == 0 goto l0_%=;				\
1051	r1 = 19;					\
1052	r0 += r1;					\
1053	r1 = *(u32*)(r0 + 0);				\
1054	r1 &= 31;					\
1055	r1 += r0;					\
1056	r0 = *(u32*)(r1 + 0);				\
1057l0_%=:	exit;						\
1058"	:
1059	: __imm(bpf_map_lookup_elem),
1060	  __imm_addr(map_array_48b)
1061	: __clobber_all);
1062}
1063
1064SEC("socket")
1065__description("map access: value_ptr += unknown scalar, 1")
1066__success __success_unpriv __retval(1)
1067__naked void value_ptr_unknown_scalar_1(void)
1068{
1069	asm volatile ("					\
1070	r1 = 0;						\
1071	*(u64*)(r10 - 8) = r1;				\
1072	r2 = r10;					\
1073	r2 += -8;					\
1074	r1 = %[map_array_48b] ll;			\
1075	call %[bpf_map_lookup_elem];			\
1076	if r0 == 0 goto l0_%=;				\
1077	r1 = *(u8*)(r0 + 0);				\
1078	r1 &= 0xf;					\
1079	r0 += r1;					\
1080	r1 = *(u8*)(r0 + 0);				\
1081l0_%=:	r0 = 1;						\
1082	exit;						\
1083"	:
1084	: __imm(bpf_map_lookup_elem),
1085	  __imm_addr(map_array_48b)
1086	: __clobber_all);
1087}
1088
1089SEC("socket")
1090__description("map access: value_ptr += unknown scalar, 2")
1091__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1092__naked void value_ptr_unknown_scalar_2_1(void)
1093{
1094	asm volatile ("					\
1095	r1 = 0;						\
1096	*(u64*)(r10 - 8) = r1;				\
1097	r2 = r10;					\
1098	r2 += -8;					\
1099	r1 = %[map_array_48b] ll;			\
1100	call %[bpf_map_lookup_elem];			\
1101	if r0 == 0 goto l0_%=;				\
1102	r1 = *(u32*)(r0 + 0);				\
1103	r1 &= 31;					\
1104	r0 += r1;					\
1105	r0 = *(u32*)(r0 + 0);				\
1106l0_%=:	exit;						\
1107"	:
1108	: __imm(bpf_map_lookup_elem),
1109	  __imm_addr(map_array_48b)
1110	: __clobber_all);
1111}
1112
1113SEC("socket")
1114__description("map access: value_ptr += unknown scalar, 3")
1115__success __success_unpriv __retval(1)
1116__naked void value_ptr_unknown_scalar_3(void)
1117{
1118	asm volatile ("					\
1119	r1 = 0;						\
1120	*(u64*)(r10 - 8) = r1;				\
1121	r2 = r10;					\
1122	r2 += -8;					\
1123	r1 = %[map_array_48b] ll;			\
1124	call %[bpf_map_lookup_elem];			\
1125	if r0 == 0 goto l0_%=;				\
1126	r1 = *(u64*)(r0 + 0);				\
1127	r2 = *(u64*)(r0 + 8);				\
1128	r3 = *(u64*)(r0 + 16);				\
1129	r1 &= 0xf;					\
1130	r3 &= 1;					\
1131	r3 |= 1;					\
1132	if r2 > r3 goto l0_%=;				\
1133	r0 += r3;					\
1134	r0 = *(u8*)(r0 + 0);				\
1135	r0 = 1;						\
1136l1_%=:	exit;						\
1137l0_%=:	r0 = 2;						\
1138	goto l1_%=;					\
1139"	:
1140	: __imm(bpf_map_lookup_elem),
1141	  __imm_addr(map_array_48b)
1142	: __clobber_all);
1143}
1144
1145SEC("socket")
1146__description("map access: value_ptr += value_ptr")
1147__failure __msg("R0 pointer += pointer prohibited")
1148__failure_unpriv
1149__naked void access_value_ptr_value_ptr_1(void)
1150{
1151	asm volatile ("					\
1152	r1 = 0;						\
1153	*(u64*)(r10 - 8) = r1;				\
1154	r2 = r10;					\
1155	r2 += -8;					\
1156	r1 = %[map_array_48b] ll;			\
1157	call %[bpf_map_lookup_elem];			\
1158	if r0 == 0 goto l0_%=;				\
1159	r0 += r0;					\
1160	r1 = *(u8*)(r0 + 0);				\
1161l0_%=:	r0 = 1;						\
1162	exit;						\
1163"	:
1164	: __imm(bpf_map_lookup_elem),
1165	  __imm_addr(map_array_48b)
1166	: __clobber_all);
1167}
1168
1169SEC("socket")
1170__description("map access: known scalar -= value_ptr")
1171__failure __msg("R1 tried to subtract pointer from scalar")
1172__failure_unpriv
1173__naked void access_known_scalar_value_ptr_2(void)
1174{
1175	asm volatile ("					\
1176	r1 = 0;						\
1177	*(u64*)(r10 - 8) = r1;				\
1178	r2 = r10;					\
1179	r2 += -8;					\
1180	r1 = %[map_array_48b] ll;			\
1181	call %[bpf_map_lookup_elem];			\
1182	if r0 == 0 goto l0_%=;				\
1183	r1 = 4;						\
1184	r1 -= r0;					\
1185	r0 = *(u8*)(r1 + 0);				\
1186l0_%=:	r0 = 1;						\
1187	exit;						\
1188"	:
1189	: __imm(bpf_map_lookup_elem),
1190	  __imm_addr(map_array_48b)
1191	: __clobber_all);
1192}
1193
1194SEC("socket")
1195__description("map access: value_ptr -= known scalar")
1196__failure __msg("R0 min value is outside of the allowed memory range")
1197__failure_unpriv
1198__naked void access_value_ptr_known_scalar(void)
1199{
1200	asm volatile ("					\
1201	r1 = 0;						\
1202	*(u64*)(r10 - 8) = r1;				\
1203	r2 = r10;					\
1204	r2 += -8;					\
1205	r1 = %[map_array_48b] ll;			\
1206	call %[bpf_map_lookup_elem];			\
1207	if r0 == 0 goto l0_%=;				\
1208	r1 = 4;						\
1209	r0 -= r1;					\
1210	r1 = *(u8*)(r0 + 0);				\
1211l0_%=:	r0 = 1;						\
1212	exit;						\
1213"	:
1214	: __imm(bpf_map_lookup_elem),
1215	  __imm_addr(map_array_48b)
1216	: __clobber_all);
1217}
1218
1219SEC("socket")
1220__description("map access: value_ptr -= known scalar, 2")
1221__success __success_unpriv __retval(1)
1222__naked void value_ptr_known_scalar_2_2(void)
1223{
1224	asm volatile ("					\
1225	r1 = 0;						\
1226	*(u64*)(r10 - 8) = r1;				\
1227	r2 = r10;					\
1228	r2 += -8;					\
1229	r1 = %[map_array_48b] ll;			\
1230	call %[bpf_map_lookup_elem];			\
1231	if r0 == 0 goto l0_%=;				\
1232	r1 = 6;						\
1233	r2 = 4;						\
1234	r0 += r1;					\
1235	r0 -= r2;					\
1236	r1 = *(u8*)(r0 + 0);				\
1237l0_%=:	r0 = 1;						\
1238	exit;						\
1239"	:
1240	: __imm(bpf_map_lookup_elem),
1241	  __imm_addr(map_array_48b)
1242	: __clobber_all);
1243}
1244
1245SEC("socket")
1246__description("map access: unknown scalar -= value_ptr")
1247__failure __msg("R1 tried to subtract pointer from scalar")
1248__failure_unpriv
1249__naked void access_unknown_scalar_value_ptr(void)
1250{
1251	asm volatile ("					\
1252	r1 = 0;						\
1253	*(u64*)(r10 - 8) = r1;				\
1254	r2 = r10;					\
1255	r2 += -8;					\
1256	r1 = %[map_array_48b] ll;			\
1257	call %[bpf_map_lookup_elem];			\
1258	if r0 == 0 goto l0_%=;				\
1259	r1 = *(u8*)(r0 + 0);				\
1260	r1 &= 0xf;					\
1261	r1 -= r0;					\
1262	r0 = *(u8*)(r1 + 0);				\
1263l0_%=:	r0 = 1;						\
1264	exit;						\
1265"	:
1266	: __imm(bpf_map_lookup_elem),
1267	  __imm_addr(map_array_48b)
1268	: __clobber_all);
1269}
1270
1271SEC("socket")
1272__description("map access: value_ptr -= unknown scalar")
1273__failure __msg("R0 min value is negative")
1274__failure_unpriv
1275__naked void access_value_ptr_unknown_scalar(void)
1276{
1277	asm volatile ("					\
1278	r1 = 0;						\
1279	*(u64*)(r10 - 8) = r1;				\
1280	r2 = r10;					\
1281	r2 += -8;					\
1282	r1 = %[map_array_48b] ll;			\
1283	call %[bpf_map_lookup_elem];			\
1284	if r0 == 0 goto l0_%=;				\
1285	r1 = *(u8*)(r0 + 0);				\
1286	r1 &= 0xf;					\
1287	r0 -= r1;					\
1288	r1 = *(u8*)(r0 + 0);				\
1289l0_%=:	r0 = 1;						\
1290	exit;						\
1291"	:
1292	: __imm(bpf_map_lookup_elem),
1293	  __imm_addr(map_array_48b)
1294	: __clobber_all);
1295}
1296
1297SEC("socket")
1298__description("map access: value_ptr -= unknown scalar, 2")
1299__success __failure_unpriv
1300__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
1301__retval(1)
1302__naked void value_ptr_unknown_scalar_2_2(void)
1303{
1304	asm volatile ("					\
1305	r1 = 0;						\
1306	*(u64*)(r10 - 8) = r1;				\
1307	r2 = r10;					\
1308	r2 += -8;					\
1309	r1 = %[map_array_48b] ll;			\
1310	call %[bpf_map_lookup_elem];			\
1311	if r0 == 0 goto l0_%=;				\
1312	r1 = *(u8*)(r0 + 0);				\
1313	r1 &= 0xf;					\
1314	r1 |= 0x7;					\
1315	r0 += r1;					\
1316	r1 = *(u8*)(r0 + 0);				\
1317	r1 &= 0x7;					\
1318	r0 -= r1;					\
1319	r1 = *(u8*)(r0 + 0);				\
1320l0_%=:	r0 = 1;						\
1321	exit;						\
1322"	:
1323	: __imm(bpf_map_lookup_elem),
1324	  __imm_addr(map_array_48b)
1325	: __clobber_all);
1326}
1327
1328SEC("socket")
1329__description("map access: value_ptr -= value_ptr")
1330__failure __msg("R0 invalid mem access 'scalar'")
1331__msg_unpriv("R0 pointer -= pointer prohibited")
1332__naked void access_value_ptr_value_ptr_2(void)
1333{
1334	asm volatile ("					\
1335	r1 = 0;						\
1336	*(u64*)(r10 - 8) = r1;				\
1337	r2 = r10;					\
1338	r2 += -8;					\
1339	r1 = %[map_array_48b] ll;			\
1340	call %[bpf_map_lookup_elem];			\
1341	if r0 == 0 goto l0_%=;				\
1342	r0 -= r0;					\
1343	r1 = *(u8*)(r0 + 0);				\
1344l0_%=:	r0 = 1;						\
1345	exit;						\
1346"	:
1347	: __imm(bpf_map_lookup_elem),
1348	  __imm_addr(map_array_48b)
1349	: __clobber_all);
1350}
1351
1352SEC("socket")
1353__description("map access: trying to leak tainted dst reg")
1354__failure __msg("math between map_value pointer and 4294967295 is not allowed")
1355__failure_unpriv
1356__naked void to_leak_tainted_dst_reg(void)
1357{
1358	asm volatile ("					\
1359	r0 = 0;						\
1360	r1 = 0;						\
1361	*(u64*)(r10 - 8) = r1;				\
1362	r2 = r10;					\
1363	r2 += -8;					\
1364	r1 = %[map_array_48b] ll;			\
1365	call %[bpf_map_lookup_elem];			\
1366	if r0 != 0 goto l0_%=;				\
1367	exit;						\
1368l0_%=:	r2 = r0;					\
1369	w1 = 0xFFFFFFFF;				\
1370	w1 = w1;					\
1371	r2 -= r1;					\
1372	*(u64*)(r0 + 0) = r2;				\
1373	r0 = 0;						\
1374	exit;						\
1375"	:
1376	: __imm(bpf_map_lookup_elem),
1377	  __imm_addr(map_array_48b)
1378	: __clobber_all);
1379}
1380
1381SEC("tc")
1382__description("32bit pkt_ptr -= scalar")
1383__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1384__naked void _32bit_pkt_ptr_scalar(void)
1385{
1386	asm volatile ("					\
1387	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1388	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1389	r6 = r7;					\
1390	r6 += 40;					\
1391	if r6 > r8 goto l0_%=;				\
1392	w4 = w7;					\
1393	w6 -= w4;					\
1394l0_%=:	r0 = 0;						\
1395	exit;						\
1396"	:
1397	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1398	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1399	: __clobber_all);
1400}
1401
1402SEC("tc")
1403__description("32bit scalar -= pkt_ptr")
1404__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1405__naked void _32bit_scalar_pkt_ptr(void)
1406{
1407	asm volatile ("					\
1408	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1409	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1410	r6 = r7;					\
1411	r6 += 40;					\
1412	if r6 > r8 goto l0_%=;				\
1413	w4 = w6;					\
1414	w4 -= w7;					\
1415l0_%=:	r0 = 0;						\
1416	exit;						\
1417"	:
1418	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1419	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1420	: __clobber_all);
1421}
1422
1423char _license[] SEC("license") = "GPL";
1424