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/array_access.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_ARRAY);
 17	__uint(max_entries, 1);
 18	__type(key, int);
 19	__type(value, struct test_val);
 20	__uint(map_flags, BPF_F_RDONLY_PROG);
 21} map_array_ro SEC(".maps");
 22
 23struct {
 24	__uint(type, BPF_MAP_TYPE_ARRAY);
 25	__uint(max_entries, 1);
 26	__type(key, int);
 27	__type(value, struct test_val);
 28	__uint(map_flags, BPF_F_WRONLY_PROG);
 29} map_array_wo SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_HASH);
 33	__uint(max_entries, 1);
 34	__type(key, long long);
 35	__type(value, struct test_val);
 36} map_hash_48b SEC(".maps");
 37
 38SEC("socket")
 39__description("valid map access into an array with a constant")
 40__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 41__retval(0)
 42__naked void an_array_with_a_constant_1(void)
 43{
 44	asm volatile ("					\
 45	r1 = 0;						\
 46	*(u64*)(r10 - 8) = r1;				\
 47	r2 = r10;					\
 48	r2 += -8;					\
 49	r1 = %[map_hash_48b] ll;			\
 50	call %[bpf_map_lookup_elem];			\
 51	if r0 == 0 goto l0_%=;				\
 52	r1 = %[test_val_foo];				\
 53	*(u64*)(r0 + 0) = r1;				\
 54l0_%=:	exit;						\
 55"	:
 56	: __imm(bpf_map_lookup_elem),
 57	  __imm_addr(map_hash_48b),
 58	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
 59	: __clobber_all);
 60}
 61
 62SEC("socket")
 63__description("valid map access into an array with a register")
 64__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 65__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
 66__naked void an_array_with_a_register_1(void)
 67{
 68	asm volatile ("					\
 69	r1 = 0;						\
 70	*(u64*)(r10 - 8) = r1;				\
 71	r2 = r10;					\
 72	r2 += -8;					\
 73	r1 = %[map_hash_48b] ll;			\
 74	call %[bpf_map_lookup_elem];			\
 75	if r0 == 0 goto l0_%=;				\
 76	r1 = 4;						\
 77	r1 <<= 2;					\
 78	r0 += r1;					\
 79	r1 = %[test_val_foo];				\
 80	*(u64*)(r0 + 0) = r1;				\
 81l0_%=:	exit;						\
 82"	:
 83	: __imm(bpf_map_lookup_elem),
 84	  __imm_addr(map_hash_48b),
 85	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
 86	: __clobber_all);
 87}
 88
 89SEC("socket")
 90__description("valid map access into an array with a variable")
 91__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 92__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
 93__naked void an_array_with_a_variable_1(void)
 94{
 95	asm volatile ("					\
 96	r1 = 0;						\
 97	*(u64*)(r10 - 8) = r1;				\
 98	r2 = r10;					\
 99	r2 += -8;					\
100	r1 = %[map_hash_48b] ll;			\
101	call %[bpf_map_lookup_elem];			\
102	if r0 == 0 goto l0_%=;				\
103	r1 = *(u32*)(r0 + 0);				\
104	if r1 >= %[max_entries] goto l0_%=;		\
105	r1 <<= 2;					\
106	r0 += r1;					\
107	r1 = %[test_val_foo];				\
108	*(u64*)(r0 + 0) = r1;				\
109l0_%=:	exit;						\
110"	:
111	: __imm(bpf_map_lookup_elem),
112	  __imm_addr(map_hash_48b),
113	  __imm_const(max_entries, MAX_ENTRIES),
114	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
115	: __clobber_all);
116}
117
118SEC("socket")
119__description("valid map access into an array with a signed variable")
120__success __failure_unpriv __msg_unpriv("R0 leaks addr")
121__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
122__naked void array_with_a_signed_variable(void)
123{
124	asm volatile ("					\
125	r1 = 0;						\
126	*(u64*)(r10 - 8) = r1;				\
127	r2 = r10;					\
128	r2 += -8;					\
129	r1 = %[map_hash_48b] ll;			\
130	call %[bpf_map_lookup_elem];			\
131	if r0 == 0 goto l0_%=;				\
132	r1 = *(u32*)(r0 + 0);				\
133	if w1 s> 0xffffffff goto l1_%=;			\
134	w1 = 0;						\
135l1_%=:	w2 = %[max_entries];				\
136	if r2 s> r1 goto l2_%=;				\
137	w1 = 0;						\
138l2_%=:	w1 <<= 2;					\
139	r0 += r1;					\
140	r1 = %[test_val_foo];				\
141	*(u64*)(r0 + 0) = r1;				\
142l0_%=:	exit;						\
143"	:
144	: __imm(bpf_map_lookup_elem),
145	  __imm_addr(map_hash_48b),
146	  __imm_const(max_entries, MAX_ENTRIES),
147	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
148	: __clobber_all);
149}
150
151SEC("socket")
152__description("invalid map access into an array with a constant")
153__failure __msg("invalid access to map value, value_size=48 off=48 size=8")
154__failure_unpriv
155__naked void an_array_with_a_constant_2(void)
156{
157	asm volatile ("					\
158	r1 = 0;						\
159	*(u64*)(r10 - 8) = r1;				\
160	r2 = r10;					\
161	r2 += -8;					\
162	r1 = %[map_hash_48b] ll;			\
163	call %[bpf_map_lookup_elem];			\
164	if r0 == 0 goto l0_%=;				\
165	r1 = %[test_val_foo];				\
166	*(u64*)(r0 + %[__imm_0]) = r1;			\
167l0_%=:	exit;						\
168"	:
169	: __imm(bpf_map_lookup_elem),
170	  __imm_addr(map_hash_48b),
171	  __imm_const(__imm_0, (MAX_ENTRIES + 1) << 2),
172	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
173	: __clobber_all);
174}
175
176SEC("socket")
177__description("invalid map access into an array with a register")
178__failure __msg("R0 min value is outside of the allowed memory range")
179__failure_unpriv
180__flag(BPF_F_ANY_ALIGNMENT)
181__naked void an_array_with_a_register_2(void)
182{
183	asm volatile ("					\
184	r1 = 0;						\
185	*(u64*)(r10 - 8) = r1;				\
186	r2 = r10;					\
187	r2 += -8;					\
188	r1 = %[map_hash_48b] ll;			\
189	call %[bpf_map_lookup_elem];			\
190	if r0 == 0 goto l0_%=;				\
191	r1 = %[__imm_0];				\
192	r1 <<= 2;					\
193	r0 += r1;					\
194	r1 = %[test_val_foo];				\
195	*(u64*)(r0 + 0) = r1;				\
196l0_%=:	exit;						\
197"	:
198	: __imm(bpf_map_lookup_elem),
199	  __imm_addr(map_hash_48b),
200	  __imm_const(__imm_0, MAX_ENTRIES + 1),
201	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
202	: __clobber_all);
203}
204
205SEC("socket")
206__description("invalid map access into an array with a variable")
207__failure
208__msg("R0 unbounded memory access, make sure to bounds check any such access")
209__failure_unpriv
210__flag(BPF_F_ANY_ALIGNMENT)
211__naked void an_array_with_a_variable_2(void)
212{
213	asm volatile ("					\
214	r1 = 0;						\
215	*(u64*)(r10 - 8) = r1;				\
216	r2 = r10;					\
217	r2 += -8;					\
218	r1 = %[map_hash_48b] ll;			\
219	call %[bpf_map_lookup_elem];			\
220	if r0 == 0 goto l0_%=;				\
221	r1 = *(u32*)(r0 + 0);				\
222	r1 <<= 2;					\
223	r0 += r1;					\
224	r1 = %[test_val_foo];				\
225	*(u64*)(r0 + 0) = r1;				\
226l0_%=:	exit;						\
227"	:
228	: __imm(bpf_map_lookup_elem),
229	  __imm_addr(map_hash_48b),
230	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
231	: __clobber_all);
232}
233
234SEC("socket")
235__description("invalid map access into an array with no floor check")
236__failure __msg("R0 unbounded memory access")
237__failure_unpriv __msg_unpriv("R0 leaks addr")
238__flag(BPF_F_ANY_ALIGNMENT)
239__naked void array_with_no_floor_check(void)
240{
241	asm volatile ("					\
242	r1 = 0;						\
243	*(u64*)(r10 - 8) = r1;				\
244	r2 = r10;					\
245	r2 += -8;					\
246	r1 = %[map_hash_48b] ll;			\
247	call %[bpf_map_lookup_elem];			\
248	if r0 == 0 goto l0_%=;				\
249	r1 = *(u64*)(r0 + 0);				\
250	w2 = %[max_entries];				\
251	if r2 s> r1 goto l1_%=;				\
252	w1 = 0;						\
253l1_%=:	w1 <<= 2;					\
254	r0 += r1;					\
255	r1 = %[test_val_foo];				\
256	*(u64*)(r0 + 0) = r1;				\
257l0_%=:	exit;						\
258"	:
259	: __imm(bpf_map_lookup_elem),
260	  __imm_addr(map_hash_48b),
261	  __imm_const(max_entries, MAX_ENTRIES),
262	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
263	: __clobber_all);
264}
265
266SEC("socket")
267__description("invalid map access into an array with a invalid max check")
268__failure __msg("invalid access to map value, value_size=48 off=44 size=8")
269__failure_unpriv __msg_unpriv("R0 leaks addr")
270__flag(BPF_F_ANY_ALIGNMENT)
271__naked void with_a_invalid_max_check_1(void)
272{
273	asm volatile ("					\
274	r1 = 0;						\
275	*(u64*)(r10 - 8) = r1;				\
276	r2 = r10;					\
277	r2 += -8;					\
278	r1 = %[map_hash_48b] ll;			\
279	call %[bpf_map_lookup_elem];			\
280	if r0 == 0 goto l0_%=;				\
281	r1 = *(u32*)(r0 + 0);				\
282	w2 = %[__imm_0];				\
283	if r2 > r1 goto l1_%=;				\
284	w1 = 0;						\
285l1_%=:	w1 <<= 2;					\
286	r0 += r1;					\
287	r1 = %[test_val_foo];				\
288	*(u64*)(r0 + 0) = r1;				\
289l0_%=:	exit;						\
290"	:
291	: __imm(bpf_map_lookup_elem),
292	  __imm_addr(map_hash_48b),
293	  __imm_const(__imm_0, MAX_ENTRIES + 1),
294	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
295	: __clobber_all);
296}
297
298SEC("socket")
299__description("invalid map access into an array with a invalid max check")
300__failure __msg("R0 pointer += pointer")
301__failure_unpriv
302__flag(BPF_F_ANY_ALIGNMENT)
303__naked void with_a_invalid_max_check_2(void)
304{
305	asm volatile ("					\
306	r1 = 0;						\
307	*(u64*)(r10 - 8) = r1;				\
308	r2 = r10;					\
309	r2 += -8;					\
310	r1 = %[map_hash_48b] ll;			\
311	call %[bpf_map_lookup_elem];			\
312	if r0 == 0 goto l0_%=;				\
313	r8 = r0;					\
314	r1 = 0;						\
315	*(u64*)(r10 - 8) = r1;				\
316	r2 = r10;					\
317	r2 += -8;					\
318	r1 = %[map_hash_48b] ll;			\
319	call %[bpf_map_lookup_elem];			\
320	if r0 == 0 goto l0_%=;				\
321	r0 += r8;					\
322	r0 = *(u32*)(r0 + %[test_val_foo]);		\
323l0_%=:	exit;						\
324"	:
325	: __imm(bpf_map_lookup_elem),
326	  __imm_addr(map_hash_48b),
327	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
328	: __clobber_all);
329}
330
331SEC("socket")
332__description("valid read map access into a read-only array 1")
333__success __success_unpriv __retval(28)
334__naked void a_read_only_array_1_1(void)
335{
336	asm volatile ("					\
337	r1 = 0;						\
338	*(u64*)(r10 - 8) = r1;				\
339	r2 = r10;					\
340	r2 += -8;					\
341	r1 = %[map_array_ro] ll;			\
342	call %[bpf_map_lookup_elem];			\
343	if r0 == 0 goto l0_%=;				\
344	r0 = *(u32*)(r0 + 0);				\
345l0_%=:	exit;						\
346"	:
347	: __imm(bpf_map_lookup_elem),
348	  __imm_addr(map_array_ro)
349	: __clobber_all);
350}
351
352SEC("tc")
353__description("valid read map access into a read-only array 2")
354__success __retval(65507)
355__naked void a_read_only_array_2_1(void)
356{
357	asm volatile ("					\
358	r1 = 0;						\
359	*(u64*)(r10 - 8) = r1;				\
360	r2 = r10;					\
361	r2 += -8;					\
362	r1 = %[map_array_ro] ll;			\
363	call %[bpf_map_lookup_elem];			\
364	if r0 == 0 goto l0_%=;				\
365	r1 = r0;					\
366	r2 = 4;						\
367	r3 = 0;						\
368	r4 = 0;						\
369	r5 = 0;						\
370	call %[bpf_csum_diff];				\
371l0_%=:	exit;						\
 
372"	:
373	: __imm(bpf_csum_diff),
374	  __imm(bpf_map_lookup_elem),
375	  __imm_addr(map_array_ro)
376	: __clobber_all);
377}
378
379SEC("socket")
380__description("invalid write map access into a read-only array 1")
381__failure __msg("write into map forbidden")
382__failure_unpriv
383__naked void a_read_only_array_1_2(void)
384{
385	asm volatile ("					\
386	r1 = 0;						\
387	*(u64*)(r10 - 8) = r1;				\
388	r2 = r10;					\
389	r2 += -8;					\
390	r1 = %[map_array_ro] ll;			\
391	call %[bpf_map_lookup_elem];			\
392	if r0 == 0 goto l0_%=;				\
393	r1 = 42;					\
394	*(u64*)(r0 + 0) = r1;				\
395l0_%=:	exit;						\
396"	:
397	: __imm(bpf_map_lookup_elem),
398	  __imm_addr(map_array_ro)
399	: __clobber_all);
400}
401
402SEC("tc")
403__description("invalid write map access into a read-only array 2")
404__failure __msg("write into map forbidden")
405__naked void a_read_only_array_2_2(void)
406{
407	asm volatile ("					\
408	r6 = r1;					\
409	r1 = 0;						\
410	*(u64*)(r10 - 8) = r1;				\
411	r2 = r10;					\
412	r2 += -8;					\
413	r1 = %[map_array_ro] ll;			\
414	call %[bpf_map_lookup_elem];			\
415	if r0 == 0 goto l0_%=;				\
416	r1 = r6;					\
417	r2 = 0;						\
418	r3 = r0;					\
419	r4 = 8;						\
420	call %[bpf_skb_load_bytes];			\
421l0_%=:	exit;						\
422"	:
423	: __imm(bpf_map_lookup_elem),
424	  __imm(bpf_skb_load_bytes),
425	  __imm_addr(map_array_ro)
426	: __clobber_all);
427}
428
429SEC("socket")
430__description("valid write map access into a write-only array 1")
431__success __success_unpriv __retval(1)
432__naked void a_write_only_array_1_1(void)
433{
434	asm volatile ("					\
435	r1 = 0;						\
436	*(u64*)(r10 - 8) = r1;				\
437	r2 = r10;					\
438	r2 += -8;					\
439	r1 = %[map_array_wo] ll;			\
440	call %[bpf_map_lookup_elem];			\
441	if r0 == 0 goto l0_%=;				\
442	r1 = 42;					\
443	*(u64*)(r0 + 0) = r1;				\
444l0_%=:	r0 = 1;						\
445	exit;						\
446"	:
447	: __imm(bpf_map_lookup_elem),
448	  __imm_addr(map_array_wo)
449	: __clobber_all);
450}
451
452SEC("tc")
453__description("valid write map access into a write-only array 2")
454__success __retval(0)
455__naked void a_write_only_array_2_1(void)
456{
457	asm volatile ("					\
458	r6 = r1;					\
459	r1 = 0;						\
460	*(u64*)(r10 - 8) = r1;				\
461	r2 = r10;					\
462	r2 += -8;					\
463	r1 = %[map_array_wo] ll;			\
464	call %[bpf_map_lookup_elem];			\
465	if r0 == 0 goto l0_%=;				\
466	r1 = r6;					\
467	r2 = 0;						\
468	r3 = r0;					\
469	r4 = 8;						\
470	call %[bpf_skb_load_bytes];			\
471l0_%=:	exit;						\
472"	:
473	: __imm(bpf_map_lookup_elem),
474	  __imm(bpf_skb_load_bytes),
475	  __imm_addr(map_array_wo)
476	: __clobber_all);
477}
478
479SEC("socket")
480__description("invalid read map access into a write-only array 1")
481__failure __msg("read from map forbidden")
482__failure_unpriv
483__naked void a_write_only_array_1_2(void)
484{
485	asm volatile ("					\
486	r1 = 0;						\
487	*(u64*)(r10 - 8) = r1;				\
488	r2 = r10;					\
489	r2 += -8;					\
490	r1 = %[map_array_wo] ll;			\
491	call %[bpf_map_lookup_elem];			\
492	if r0 == 0 goto l0_%=;				\
493	r0 = *(u64*)(r0 + 0);				\
494l0_%=:	exit;						\
495"	:
496	: __imm(bpf_map_lookup_elem),
497	  __imm_addr(map_array_wo)
498	: __clobber_all);
499}
500
501SEC("tc")
502__description("invalid read map access into a write-only array 2")
503__failure __msg("read from map forbidden")
504__naked void a_write_only_array_2_2(void)
505{
506	asm volatile ("					\
507	r1 = 0;						\
508	*(u64*)(r10 - 8) = r1;				\
509	r2 = r10;					\
510	r2 += -8;					\
511	r1 = %[map_array_wo] ll;			\
512	call %[bpf_map_lookup_elem];			\
513	if r0 == 0 goto l0_%=;				\
514	r1 = r0;					\
515	r2 = 4;						\
516	r3 = 0;						\
517	r4 = 0;						\
518	r5 = 0;						\
519	call %[bpf_csum_diff];				\
520l0_%=:	exit;						\
521"	:
522	: __imm(bpf_csum_diff),
523	  __imm(bpf_map_lookup_elem),
524	  __imm_addr(map_array_wo)
525	: __clobber_all);
526}
527
528char _license[] SEC("license") = "GPL";
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/* Converted from tools/testing/selftests/bpf/verifier/array_access.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_ARRAY);
 17	__uint(max_entries, 1);
 18	__type(key, int);
 19	__type(value, struct test_val);
 20	__uint(map_flags, BPF_F_RDONLY_PROG);
 21} map_array_ro SEC(".maps");
 22
 23struct {
 24	__uint(type, BPF_MAP_TYPE_ARRAY);
 25	__uint(max_entries, 1);
 26	__type(key, int);
 27	__type(value, struct test_val);
 28	__uint(map_flags, BPF_F_WRONLY_PROG);
 29} map_array_wo SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_HASH);
 33	__uint(max_entries, 1);
 34	__type(key, long long);
 35	__type(value, struct test_val);
 36} map_hash_48b SEC(".maps");
 37
 38SEC("socket")
 39__description("valid map access into an array with a constant")
 40__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 41__retval(0)
 42__naked void an_array_with_a_constant_1(void)
 43{
 44	asm volatile ("					\
 45	r1 = 0;						\
 46	*(u64*)(r10 - 8) = r1;				\
 47	r2 = r10;					\
 48	r2 += -8;					\
 49	r1 = %[map_hash_48b] ll;			\
 50	call %[bpf_map_lookup_elem];			\
 51	if r0 == 0 goto l0_%=;				\
 52	r1 = %[test_val_foo];				\
 53	*(u64*)(r0 + 0) = r1;				\
 54l0_%=:	exit;						\
 55"	:
 56	: __imm(bpf_map_lookup_elem),
 57	  __imm_addr(map_hash_48b),
 58	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
 59	: __clobber_all);
 60}
 61
 62SEC("socket")
 63__description("valid map access into an array with a register")
 64__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 65__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
 66__naked void an_array_with_a_register_1(void)
 67{
 68	asm volatile ("					\
 69	r1 = 0;						\
 70	*(u64*)(r10 - 8) = r1;				\
 71	r2 = r10;					\
 72	r2 += -8;					\
 73	r1 = %[map_hash_48b] ll;			\
 74	call %[bpf_map_lookup_elem];			\
 75	if r0 == 0 goto l0_%=;				\
 76	r1 = 4;						\
 77	r1 <<= 2;					\
 78	r0 += r1;					\
 79	r1 = %[test_val_foo];				\
 80	*(u64*)(r0 + 0) = r1;				\
 81l0_%=:	exit;						\
 82"	:
 83	: __imm(bpf_map_lookup_elem),
 84	  __imm_addr(map_hash_48b),
 85	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
 86	: __clobber_all);
 87}
 88
 89SEC("socket")
 90__description("valid map access into an array with a variable")
 91__success __failure_unpriv __msg_unpriv("R0 leaks addr")
 92__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
 93__naked void an_array_with_a_variable_1(void)
 94{
 95	asm volatile ("					\
 96	r1 = 0;						\
 97	*(u64*)(r10 - 8) = r1;				\
 98	r2 = r10;					\
 99	r2 += -8;					\
100	r1 = %[map_hash_48b] ll;			\
101	call %[bpf_map_lookup_elem];			\
102	if r0 == 0 goto l0_%=;				\
103	r1 = *(u32*)(r0 + 0);				\
104	if r1 >= %[max_entries] goto l0_%=;		\
105	r1 <<= 2;					\
106	r0 += r1;					\
107	r1 = %[test_val_foo];				\
108	*(u64*)(r0 + 0) = r1;				\
109l0_%=:	exit;						\
110"	:
111	: __imm(bpf_map_lookup_elem),
112	  __imm_addr(map_hash_48b),
113	  __imm_const(max_entries, MAX_ENTRIES),
114	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
115	: __clobber_all);
116}
117
118SEC("socket")
119__description("valid map access into an array with a signed variable")
120__success __failure_unpriv __msg_unpriv("R0 leaks addr")
121__retval(0) __flag(BPF_F_ANY_ALIGNMENT)
122__naked void array_with_a_signed_variable(void)
123{
124	asm volatile ("					\
125	r1 = 0;						\
126	*(u64*)(r10 - 8) = r1;				\
127	r2 = r10;					\
128	r2 += -8;					\
129	r1 = %[map_hash_48b] ll;			\
130	call %[bpf_map_lookup_elem];			\
131	if r0 == 0 goto l0_%=;				\
132	r1 = *(u32*)(r0 + 0);				\
133	if w1 s> 0xffffffff goto l1_%=;			\
134	w1 = 0;						\
135l1_%=:	w2 = %[max_entries];				\
136	if r2 s> r1 goto l2_%=;				\
137	w1 = 0;						\
138l2_%=:	w1 <<= 2;					\
139	r0 += r1;					\
140	r1 = %[test_val_foo];				\
141	*(u64*)(r0 + 0) = r1;				\
142l0_%=:	exit;						\
143"	:
144	: __imm(bpf_map_lookup_elem),
145	  __imm_addr(map_hash_48b),
146	  __imm_const(max_entries, MAX_ENTRIES),
147	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
148	: __clobber_all);
149}
150
151SEC("socket")
152__description("invalid map access into an array with a constant")
153__failure __msg("invalid access to map value, value_size=48 off=48 size=8")
154__failure_unpriv
155__naked void an_array_with_a_constant_2(void)
156{
157	asm volatile ("					\
158	r1 = 0;						\
159	*(u64*)(r10 - 8) = r1;				\
160	r2 = r10;					\
161	r2 += -8;					\
162	r1 = %[map_hash_48b] ll;			\
163	call %[bpf_map_lookup_elem];			\
164	if r0 == 0 goto l0_%=;				\
165	r1 = %[test_val_foo];				\
166	*(u64*)(r0 + %[__imm_0]) = r1;			\
167l0_%=:	exit;						\
168"	:
169	: __imm(bpf_map_lookup_elem),
170	  __imm_addr(map_hash_48b),
171	  __imm_const(__imm_0, (MAX_ENTRIES + 1) << 2),
172	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
173	: __clobber_all);
174}
175
176SEC("socket")
177__description("invalid map access into an array with a register")
178__failure __msg("R0 min value is outside of the allowed memory range")
179__failure_unpriv
180__flag(BPF_F_ANY_ALIGNMENT)
181__naked void an_array_with_a_register_2(void)
182{
183	asm volatile ("					\
184	r1 = 0;						\
185	*(u64*)(r10 - 8) = r1;				\
186	r2 = r10;					\
187	r2 += -8;					\
188	r1 = %[map_hash_48b] ll;			\
189	call %[bpf_map_lookup_elem];			\
190	if r0 == 0 goto l0_%=;				\
191	r1 = %[__imm_0];				\
192	r1 <<= 2;					\
193	r0 += r1;					\
194	r1 = %[test_val_foo];				\
195	*(u64*)(r0 + 0) = r1;				\
196l0_%=:	exit;						\
197"	:
198	: __imm(bpf_map_lookup_elem),
199	  __imm_addr(map_hash_48b),
200	  __imm_const(__imm_0, MAX_ENTRIES + 1),
201	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
202	: __clobber_all);
203}
204
205SEC("socket")
206__description("invalid map access into an array with a variable")
207__failure
208__msg("R0 unbounded memory access, make sure to bounds check any such access")
209__failure_unpriv
210__flag(BPF_F_ANY_ALIGNMENT)
211__naked void an_array_with_a_variable_2(void)
212{
213	asm volatile ("					\
214	r1 = 0;						\
215	*(u64*)(r10 - 8) = r1;				\
216	r2 = r10;					\
217	r2 += -8;					\
218	r1 = %[map_hash_48b] ll;			\
219	call %[bpf_map_lookup_elem];			\
220	if r0 == 0 goto l0_%=;				\
221	r1 = *(u32*)(r0 + 0);				\
222	r1 <<= 2;					\
223	r0 += r1;					\
224	r1 = %[test_val_foo];				\
225	*(u64*)(r0 + 0) = r1;				\
226l0_%=:	exit;						\
227"	:
228	: __imm(bpf_map_lookup_elem),
229	  __imm_addr(map_hash_48b),
230	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
231	: __clobber_all);
232}
233
234SEC("socket")
235__description("invalid map access into an array with no floor check")
236__failure __msg("R0 unbounded memory access")
237__failure_unpriv __msg_unpriv("R0 leaks addr")
238__flag(BPF_F_ANY_ALIGNMENT)
239__naked void array_with_no_floor_check(void)
240{
241	asm volatile ("					\
242	r1 = 0;						\
243	*(u64*)(r10 - 8) = r1;				\
244	r2 = r10;					\
245	r2 += -8;					\
246	r1 = %[map_hash_48b] ll;			\
247	call %[bpf_map_lookup_elem];			\
248	if r0 == 0 goto l0_%=;				\
249	r1 = *(u64*)(r0 + 0);				\
250	w2 = %[max_entries];				\
251	if r2 s> r1 goto l1_%=;				\
252	w1 = 0;						\
253l1_%=:	w1 <<= 2;					\
254	r0 += r1;					\
255	r1 = %[test_val_foo];				\
256	*(u64*)(r0 + 0) = r1;				\
257l0_%=:	exit;						\
258"	:
259	: __imm(bpf_map_lookup_elem),
260	  __imm_addr(map_hash_48b),
261	  __imm_const(max_entries, MAX_ENTRIES),
262	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
263	: __clobber_all);
264}
265
266SEC("socket")
267__description("invalid map access into an array with a invalid max check")
268__failure __msg("invalid access to map value, value_size=48 off=44 size=8")
269__failure_unpriv __msg_unpriv("R0 leaks addr")
270__flag(BPF_F_ANY_ALIGNMENT)
271__naked void with_a_invalid_max_check_1(void)
272{
273	asm volatile ("					\
274	r1 = 0;						\
275	*(u64*)(r10 - 8) = r1;				\
276	r2 = r10;					\
277	r2 += -8;					\
278	r1 = %[map_hash_48b] ll;			\
279	call %[bpf_map_lookup_elem];			\
280	if r0 == 0 goto l0_%=;				\
281	r1 = *(u32*)(r0 + 0);				\
282	w2 = %[__imm_0];				\
283	if r2 > r1 goto l1_%=;				\
284	w1 = 0;						\
285l1_%=:	w1 <<= 2;					\
286	r0 += r1;					\
287	r1 = %[test_val_foo];				\
288	*(u64*)(r0 + 0) = r1;				\
289l0_%=:	exit;						\
290"	:
291	: __imm(bpf_map_lookup_elem),
292	  __imm_addr(map_hash_48b),
293	  __imm_const(__imm_0, MAX_ENTRIES + 1),
294	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
295	: __clobber_all);
296}
297
298SEC("socket")
299__description("invalid map access into an array with a invalid max check")
300__failure __msg("R0 pointer += pointer")
301__failure_unpriv
302__flag(BPF_F_ANY_ALIGNMENT)
303__naked void with_a_invalid_max_check_2(void)
304{
305	asm volatile ("					\
306	r1 = 0;						\
307	*(u64*)(r10 - 8) = r1;				\
308	r2 = r10;					\
309	r2 += -8;					\
310	r1 = %[map_hash_48b] ll;			\
311	call %[bpf_map_lookup_elem];			\
312	if r0 == 0 goto l0_%=;				\
313	r8 = r0;					\
314	r1 = 0;						\
315	*(u64*)(r10 - 8) = r1;				\
316	r2 = r10;					\
317	r2 += -8;					\
318	r1 = %[map_hash_48b] ll;			\
319	call %[bpf_map_lookup_elem];			\
320	if r0 == 0 goto l0_%=;				\
321	r0 += r8;					\
322	r0 = *(u32*)(r0 + %[test_val_foo]);		\
323l0_%=:	exit;						\
324"	:
325	: __imm(bpf_map_lookup_elem),
326	  __imm_addr(map_hash_48b),
327	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
328	: __clobber_all);
329}
330
331SEC("socket")
332__description("valid read map access into a read-only array 1")
333__success __success_unpriv __retval(28)
334__naked void a_read_only_array_1_1(void)
335{
336	asm volatile ("					\
337	r1 = 0;						\
338	*(u64*)(r10 - 8) = r1;				\
339	r2 = r10;					\
340	r2 += -8;					\
341	r1 = %[map_array_ro] ll;			\
342	call %[bpf_map_lookup_elem];			\
343	if r0 == 0 goto l0_%=;				\
344	r0 = *(u32*)(r0 + 0);				\
345l0_%=:	exit;						\
346"	:
347	: __imm(bpf_map_lookup_elem),
348	  __imm_addr(map_array_ro)
349	: __clobber_all);
350}
351
352SEC("tc")
353__description("valid read map access into a read-only array 2")
354__success __retval(65507)
355__naked void a_read_only_array_2_1(void)
356{
357	asm volatile ("					\
358	r1 = 0;						\
359	*(u64*)(r10 - 8) = r1;				\
360	r2 = r10;					\
361	r2 += -8;					\
362	r1 = %[map_array_ro] ll;			\
363	call %[bpf_map_lookup_elem];			\
364	if r0 == 0 goto l0_%=;				\
365	r1 = r0;					\
366	r2 = 4;						\
367	r3 = 0;						\
368	r4 = 0;						\
369	r5 = 0;						\
370	call %[bpf_csum_diff];				\
371l0_%=:	r0 &= 0xffff;					\
372	exit;						\
373"	:
374	: __imm(bpf_csum_diff),
375	  __imm(bpf_map_lookup_elem),
376	  __imm_addr(map_array_ro)
377	: __clobber_all);
378}
379
380SEC("socket")
381__description("invalid write map access into a read-only array 1")
382__failure __msg("write into map forbidden")
383__failure_unpriv
384__naked void a_read_only_array_1_2(void)
385{
386	asm volatile ("					\
387	r1 = 0;						\
388	*(u64*)(r10 - 8) = r1;				\
389	r2 = r10;					\
390	r2 += -8;					\
391	r1 = %[map_array_ro] ll;			\
392	call %[bpf_map_lookup_elem];			\
393	if r0 == 0 goto l0_%=;				\
394	r1 = 42;					\
395	*(u64*)(r0 + 0) = r1;				\
396l0_%=:	exit;						\
397"	:
398	: __imm(bpf_map_lookup_elem),
399	  __imm_addr(map_array_ro)
400	: __clobber_all);
401}
402
403SEC("tc")
404__description("invalid write map access into a read-only array 2")
405__failure __msg("write into map forbidden")
406__naked void a_read_only_array_2_2(void)
407{
408	asm volatile ("					\
409	r6 = r1;					\
410	r1 = 0;						\
411	*(u64*)(r10 - 8) = r1;				\
412	r2 = r10;					\
413	r2 += -8;					\
414	r1 = %[map_array_ro] ll;			\
415	call %[bpf_map_lookup_elem];			\
416	if r0 == 0 goto l0_%=;				\
417	r1 = r6;					\
418	r2 = 0;						\
419	r3 = r0;					\
420	r4 = 8;						\
421	call %[bpf_skb_load_bytes];			\
422l0_%=:	exit;						\
423"	:
424	: __imm(bpf_map_lookup_elem),
425	  __imm(bpf_skb_load_bytes),
426	  __imm_addr(map_array_ro)
427	: __clobber_all);
428}
429
430SEC("socket")
431__description("valid write map access into a write-only array 1")
432__success __success_unpriv __retval(1)
433__naked void a_write_only_array_1_1(void)
434{
435	asm volatile ("					\
436	r1 = 0;						\
437	*(u64*)(r10 - 8) = r1;				\
438	r2 = r10;					\
439	r2 += -8;					\
440	r1 = %[map_array_wo] ll;			\
441	call %[bpf_map_lookup_elem];			\
442	if r0 == 0 goto l0_%=;				\
443	r1 = 42;					\
444	*(u64*)(r0 + 0) = r1;				\
445l0_%=:	r0 = 1;						\
446	exit;						\
447"	:
448	: __imm(bpf_map_lookup_elem),
449	  __imm_addr(map_array_wo)
450	: __clobber_all);
451}
452
453SEC("tc")
454__description("valid write map access into a write-only array 2")
455__success __retval(0)
456__naked void a_write_only_array_2_1(void)
457{
458	asm volatile ("					\
459	r6 = r1;					\
460	r1 = 0;						\
461	*(u64*)(r10 - 8) = r1;				\
462	r2 = r10;					\
463	r2 += -8;					\
464	r1 = %[map_array_wo] ll;			\
465	call %[bpf_map_lookup_elem];			\
466	if r0 == 0 goto l0_%=;				\
467	r1 = r6;					\
468	r2 = 0;						\
469	r3 = r0;					\
470	r4 = 8;						\
471	call %[bpf_skb_load_bytes];			\
472l0_%=:	exit;						\
473"	:
474	: __imm(bpf_map_lookup_elem),
475	  __imm(bpf_skb_load_bytes),
476	  __imm_addr(map_array_wo)
477	: __clobber_all);
478}
479
480SEC("socket")
481__description("invalid read map access into a write-only array 1")
482__failure __msg("read from map forbidden")
483__failure_unpriv
484__naked void a_write_only_array_1_2(void)
485{
486	asm volatile ("					\
487	r1 = 0;						\
488	*(u64*)(r10 - 8) = r1;				\
489	r2 = r10;					\
490	r2 += -8;					\
491	r1 = %[map_array_wo] ll;			\
492	call %[bpf_map_lookup_elem];			\
493	if r0 == 0 goto l0_%=;				\
494	r0 = *(u64*)(r0 + 0);				\
495l0_%=:	exit;						\
496"	:
497	: __imm(bpf_map_lookup_elem),
498	  __imm_addr(map_array_wo)
499	: __clobber_all);
500}
501
502SEC("tc")
503__description("invalid read map access into a write-only array 2")
504__failure __msg("read from map forbidden")
505__naked void a_write_only_array_2_2(void)
506{
507	asm volatile ("					\
508	r1 = 0;						\
509	*(u64*)(r10 - 8) = r1;				\
510	r2 = r10;					\
511	r2 += -8;					\
512	r1 = %[map_array_wo] ll;			\
513	call %[bpf_map_lookup_elem];			\
514	if r0 == 0 goto l0_%=;				\
515	r1 = r0;					\
516	r2 = 4;						\
517	r3 = 0;						\
518	r4 = 0;						\
519	r5 = 0;						\
520	call %[bpf_csum_diff];				\
521l0_%=:	exit;						\
522"	:
523	: __imm(bpf_csum_diff),
524	  __imm(bpf_map_lookup_elem),
525	  __imm_addr(map_array_wo)
526	: __clobber_all);
527}
528
529char _license[] SEC("license") = "GPL";