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