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