]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/progs/verifier_array_access.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / progs / verifier_array_access.c
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
10 struct test_val {
11         unsigned int index;
12         int foo[MAX_ENTRIES];
13 };
14
15 struct {
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
23 struct {
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
31 struct {
32         __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
33         __uint(max_entries, 2);
34         __type(key, __u32);
35         __type(value, struct test_val);
36 } map_array_pcpu SEC(".maps");
37
38 struct {
39         __uint(type, BPF_MAP_TYPE_ARRAY);
40         __uint(max_entries, 2);
41         __type(key, __u32);
42         __type(value, struct test_val);
43 } map_array SEC(".maps");
44
45 struct {
46         __uint(type, BPF_MAP_TYPE_HASH);
47         __uint(max_entries, 1);
48         __type(key, long long);
49         __type(value, struct test_val);
50 } map_hash_48b SEC(".maps");
51
52 SEC("socket")
53 __description("valid map access into an array with a constant")
54 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
55 __retval(0)
56 __naked void an_array_with_a_constant_1(void)
57 {
58         asm volatile ("                                 \
59         r1 = 0;                                         \
60         *(u64*)(r10 - 8) = r1;                          \
61         r2 = r10;                                       \
62         r2 += -8;                                       \
63         r1 = %[map_hash_48b] ll;                        \
64         call %[bpf_map_lookup_elem];                    \
65         if r0 == 0 goto l0_%=;                          \
66         r1 = %[test_val_foo];                           \
67         *(u64*)(r0 + 0) = r1;                           \
68 l0_%=:  exit;                                           \
69 "       :
70         : __imm(bpf_map_lookup_elem),
71           __imm_addr(map_hash_48b),
72           __imm_const(test_val_foo, offsetof(struct test_val, foo))
73         : __clobber_all);
74 }
75
76 SEC("socket")
77 __description("valid map access into an array with a register")
78 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
79 __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
80 __naked void an_array_with_a_register_1(void)
81 {
82         asm volatile ("                                 \
83         r1 = 0;                                         \
84         *(u64*)(r10 - 8) = r1;                          \
85         r2 = r10;                                       \
86         r2 += -8;                                       \
87         r1 = %[map_hash_48b] ll;                        \
88         call %[bpf_map_lookup_elem];                    \
89         if r0 == 0 goto l0_%=;                          \
90         r1 = 4;                                         \
91         r1 <<= 2;                                       \
92         r0 += r1;                                       \
93         r1 = %[test_val_foo];                           \
94         *(u64*)(r0 + 0) = r1;                           \
95 l0_%=:  exit;                                           \
96 "       :
97         : __imm(bpf_map_lookup_elem),
98           __imm_addr(map_hash_48b),
99           __imm_const(test_val_foo, offsetof(struct test_val, foo))
100         : __clobber_all);
101 }
102
103 SEC("socket")
104 __description("valid map access into an array with a variable")
105 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
106 __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
107 __naked void an_array_with_a_variable_1(void)
108 {
109         asm volatile ("                                 \
110         r1 = 0;                                         \
111         *(u64*)(r10 - 8) = r1;                          \
112         r2 = r10;                                       \
113         r2 += -8;                                       \
114         r1 = %[map_hash_48b] ll;                        \
115         call %[bpf_map_lookup_elem];                    \
116         if r0 == 0 goto l0_%=;                          \
117         r1 = *(u32*)(r0 + 0);                           \
118         if r1 >= %[max_entries] goto l0_%=;             \
119         r1 <<= 2;                                       \
120         r0 += r1;                                       \
121         r1 = %[test_val_foo];                           \
122         *(u64*)(r0 + 0) = r1;                           \
123 l0_%=:  exit;                                           \
124 "       :
125         : __imm(bpf_map_lookup_elem),
126           __imm_addr(map_hash_48b),
127           __imm_const(max_entries, MAX_ENTRIES),
128           __imm_const(test_val_foo, offsetof(struct test_val, foo))
129         : __clobber_all);
130 }
131
132 SEC("socket")
133 __description("valid map access into an array with a signed variable")
134 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
135 __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
136 __naked void array_with_a_signed_variable(void)
137 {
138         asm volatile ("                                 \
139         r1 = 0;                                         \
140         *(u64*)(r10 - 8) = r1;                          \
141         r2 = r10;                                       \
142         r2 += -8;                                       \
143         r1 = %[map_hash_48b] ll;                        \
144         call %[bpf_map_lookup_elem];                    \
145         if r0 == 0 goto l0_%=;                          \
146         r1 = *(u32*)(r0 + 0);                           \
147         if w1 s> 0xffffffff goto l1_%=;                 \
148         w1 = 0;                                         \
149 l1_%=:  w2 = %[max_entries];                            \
150         if r2 s> r1 goto l2_%=;                         \
151         w1 = 0;                                         \
152 l2_%=:  w1 <<= 2;                                       \
153         r0 += r1;                                       \
154         r1 = %[test_val_foo];                           \
155         *(u64*)(r0 + 0) = r1;                           \
156 l0_%=:  exit;                                           \
157 "       :
158         : __imm(bpf_map_lookup_elem),
159           __imm_addr(map_hash_48b),
160           __imm_const(max_entries, MAX_ENTRIES),
161           __imm_const(test_val_foo, offsetof(struct test_val, foo))
162         : __clobber_all);
163 }
164
165 SEC("socket")
166 __description("invalid map access into an array with a constant")
167 __failure __msg("invalid access to map value, value_size=48 off=48 size=8")
168 __failure_unpriv
169 __naked void an_array_with_a_constant_2(void)
170 {
171         asm volatile ("                                 \
172         r1 = 0;                                         \
173         *(u64*)(r10 - 8) = r1;                          \
174         r2 = r10;                                       \
175         r2 += -8;                                       \
176         r1 = %[map_hash_48b] ll;                        \
177         call %[bpf_map_lookup_elem];                    \
178         if r0 == 0 goto l0_%=;                          \
179         r1 = %[test_val_foo];                           \
180         *(u64*)(r0 + %[__imm_0]) = r1;                  \
181 l0_%=:  exit;                                           \
182 "       :
183         : __imm(bpf_map_lookup_elem),
184           __imm_addr(map_hash_48b),
185           __imm_const(__imm_0, (MAX_ENTRIES + 1) << 2),
186           __imm_const(test_val_foo, offsetof(struct test_val, foo))
187         : __clobber_all);
188 }
189
190 SEC("socket")
191 __description("invalid map access into an array with a register")
192 __failure __msg("R0 min value is outside of the allowed memory range")
193 __failure_unpriv
194 __flag(BPF_F_ANY_ALIGNMENT)
195 __naked void an_array_with_a_register_2(void)
196 {
197         asm volatile ("                                 \
198         r1 = 0;                                         \
199         *(u64*)(r10 - 8) = r1;                          \
200         r2 = r10;                                       \
201         r2 += -8;                                       \
202         r1 = %[map_hash_48b] ll;                        \
203         call %[bpf_map_lookup_elem];                    \
204         if r0 == 0 goto l0_%=;                          \
205         r1 = %[__imm_0];                                \
206         r1 <<= 2;                                       \
207         r0 += r1;                                       \
208         r1 = %[test_val_foo];                           \
209         *(u64*)(r0 + 0) = r1;                           \
210 l0_%=:  exit;                                           \
211 "       :
212         : __imm(bpf_map_lookup_elem),
213           __imm_addr(map_hash_48b),
214           __imm_const(__imm_0, MAX_ENTRIES + 1),
215           __imm_const(test_val_foo, offsetof(struct test_val, foo))
216         : __clobber_all);
217 }
218
219 SEC("socket")
220 __description("invalid map access into an array with a variable")
221 __failure
222 __msg("R0 unbounded memory access, make sure to bounds check any such access")
223 __failure_unpriv
224 __flag(BPF_F_ANY_ALIGNMENT)
225 __naked void an_array_with_a_variable_2(void)
226 {
227         asm volatile ("                                 \
228         r1 = 0;                                         \
229         *(u64*)(r10 - 8) = r1;                          \
230         r2 = r10;                                       \
231         r2 += -8;                                       \
232         r1 = %[map_hash_48b] ll;                        \
233         call %[bpf_map_lookup_elem];                    \
234         if r0 == 0 goto l0_%=;                          \
235         r1 = *(u32*)(r0 + 0);                           \
236         r1 <<= 2;                                       \
237         r0 += r1;                                       \
238         r1 = %[test_val_foo];                           \
239         *(u64*)(r0 + 0) = r1;                           \
240 l0_%=:  exit;                                           \
241 "       :
242         : __imm(bpf_map_lookup_elem),
243           __imm_addr(map_hash_48b),
244           __imm_const(test_val_foo, offsetof(struct test_val, foo))
245         : __clobber_all);
246 }
247
248 SEC("socket")
249 __description("invalid map access into an array with no floor check")
250 __failure __msg("R0 unbounded memory access")
251 __failure_unpriv __msg_unpriv("R0 leaks addr")
252 __flag(BPF_F_ANY_ALIGNMENT)
253 __naked void array_with_no_floor_check(void)
254 {
255         asm volatile ("                                 \
256         r1 = 0;                                         \
257         *(u64*)(r10 - 8) = r1;                          \
258         r2 = r10;                                       \
259         r2 += -8;                                       \
260         r1 = %[map_hash_48b] ll;                        \
261         call %[bpf_map_lookup_elem];                    \
262         if r0 == 0 goto l0_%=;                          \
263         r1 = *(u64*)(r0 + 0);                           \
264         w2 = %[max_entries];                            \
265         if r2 s> r1 goto l1_%=;                         \
266         w1 = 0;                                         \
267 l1_%=:  w1 <<= 2;                                       \
268         r0 += r1;                                       \
269         r1 = %[test_val_foo];                           \
270         *(u64*)(r0 + 0) = r1;                           \
271 l0_%=:  exit;                                           \
272 "       :
273         : __imm(bpf_map_lookup_elem),
274           __imm_addr(map_hash_48b),
275           __imm_const(max_entries, MAX_ENTRIES),
276           __imm_const(test_val_foo, offsetof(struct test_val, foo))
277         : __clobber_all);
278 }
279
280 SEC("socket")
281 __description("invalid map access into an array with a invalid max check")
282 __failure __msg("invalid access to map value, value_size=48 off=44 size=8")
283 __failure_unpriv __msg_unpriv("R0 leaks addr")
284 __flag(BPF_F_ANY_ALIGNMENT)
285 __naked void with_a_invalid_max_check_1(void)
286 {
287         asm volatile ("                                 \
288         r1 = 0;                                         \
289         *(u64*)(r10 - 8) = r1;                          \
290         r2 = r10;                                       \
291         r2 += -8;                                       \
292         r1 = %[map_hash_48b] ll;                        \
293         call %[bpf_map_lookup_elem];                    \
294         if r0 == 0 goto l0_%=;                          \
295         r1 = *(u32*)(r0 + 0);                           \
296         w2 = %[__imm_0];                                \
297         if r2 > r1 goto l1_%=;                          \
298         w1 = 0;                                         \
299 l1_%=:  w1 <<= 2;                                       \
300         r0 += r1;                                       \
301         r1 = %[test_val_foo];                           \
302         *(u64*)(r0 + 0) = r1;                           \
303 l0_%=:  exit;                                           \
304 "       :
305         : __imm(bpf_map_lookup_elem),
306           __imm_addr(map_hash_48b),
307           __imm_const(__imm_0, MAX_ENTRIES + 1),
308           __imm_const(test_val_foo, offsetof(struct test_val, foo))
309         : __clobber_all);
310 }
311
312 SEC("socket")
313 __description("invalid map access into an array with a invalid max check")
314 __failure __msg("R0 pointer += pointer")
315 __failure_unpriv
316 __flag(BPF_F_ANY_ALIGNMENT)
317 __naked void with_a_invalid_max_check_2(void)
318 {
319         asm volatile ("                                 \
320         r1 = 0;                                         \
321         *(u64*)(r10 - 8) = r1;                          \
322         r2 = r10;                                       \
323         r2 += -8;                                       \
324         r1 = %[map_hash_48b] ll;                        \
325         call %[bpf_map_lookup_elem];                    \
326         if r0 == 0 goto l0_%=;                          \
327         r8 = r0;                                        \
328         r1 = 0;                                         \
329         *(u64*)(r10 - 8) = r1;                          \
330         r2 = r10;                                       \
331         r2 += -8;                                       \
332         r1 = %[map_hash_48b] ll;                        \
333         call %[bpf_map_lookup_elem];                    \
334         if r0 == 0 goto l0_%=;                          \
335         r0 += r8;                                       \
336         r0 = *(u32*)(r0 + %[test_val_foo]);             \
337 l0_%=:  exit;                                           \
338 "       :
339         : __imm(bpf_map_lookup_elem),
340           __imm_addr(map_hash_48b),
341           __imm_const(test_val_foo, offsetof(struct test_val, foo))
342         : __clobber_all);
343 }
344
345 SEC("socket")
346 __description("valid read map access into a read-only array 1")
347 __success __success_unpriv __retval(28)
348 __naked void a_read_only_array_1_1(void)
349 {
350         asm volatile ("                                 \
351         r1 = 0;                                         \
352         *(u64*)(r10 - 8) = r1;                          \
353         r2 = r10;                                       \
354         r2 += -8;                                       \
355         r1 = %[map_array_ro] ll;                        \
356         call %[bpf_map_lookup_elem];                    \
357         if r0 == 0 goto l0_%=;                          \
358         r0 = *(u32*)(r0 + 0);                           \
359 l0_%=:  exit;                                           \
360 "       :
361         : __imm(bpf_map_lookup_elem),
362           __imm_addr(map_array_ro)
363         : __clobber_all);
364 }
365
366 SEC("tc")
367 __description("valid read map access into a read-only array 2")
368 __success __retval(65507)
369 __naked void a_read_only_array_2_1(void)
370 {
371         asm volatile ("                                 \
372         r1 = 0;                                         \
373         *(u64*)(r10 - 8) = r1;                          \
374         r2 = r10;                                       \
375         r2 += -8;                                       \
376         r1 = %[map_array_ro] ll;                        \
377         call %[bpf_map_lookup_elem];                    \
378         if r0 == 0 goto l0_%=;                          \
379         r1 = r0;                                        \
380         r2 = 4;                                         \
381         r3 = 0;                                         \
382         r4 = 0;                                         \
383         r5 = 0;                                         \
384         call %[bpf_csum_diff];                          \
385 l0_%=:  exit;                                           \
386 "       :
387         : __imm(bpf_csum_diff),
388           __imm(bpf_map_lookup_elem),
389           __imm_addr(map_array_ro)
390         : __clobber_all);
391 }
392
393 SEC("socket")
394 __description("invalid write map access into a read-only array 1")
395 __failure __msg("write into map forbidden")
396 __failure_unpriv
397 __naked void a_read_only_array_1_2(void)
398 {
399         asm volatile ("                                 \
400         r1 = 0;                                         \
401         *(u64*)(r10 - 8) = r1;                          \
402         r2 = r10;                                       \
403         r2 += -8;                                       \
404         r1 = %[map_array_ro] ll;                        \
405         call %[bpf_map_lookup_elem];                    \
406         if r0 == 0 goto l0_%=;                          \
407         r1 = 42;                                        \
408         *(u64*)(r0 + 0) = r1;                           \
409 l0_%=:  exit;                                           \
410 "       :
411         : __imm(bpf_map_lookup_elem),
412           __imm_addr(map_array_ro)
413         : __clobber_all);
414 }
415
416 SEC("tc")
417 __description("invalid write map access into a read-only array 2")
418 __failure __msg("write into map forbidden")
419 __naked void a_read_only_array_2_2(void)
420 {
421         asm volatile ("                                 \
422         r6 = r1;                                        \
423         r1 = 0;                                         \
424         *(u64*)(r10 - 8) = r1;                          \
425         r2 = r10;                                       \
426         r2 += -8;                                       \
427         r1 = %[map_array_ro] ll;                        \
428         call %[bpf_map_lookup_elem];                    \
429         if r0 == 0 goto l0_%=;                          \
430         r1 = r6;                                        \
431         r2 = 0;                                         \
432         r3 = r0;                                        \
433         r4 = 8;                                         \
434         call %[bpf_skb_load_bytes];                     \
435 l0_%=:  exit;                                           \
436 "       :
437         : __imm(bpf_map_lookup_elem),
438           __imm(bpf_skb_load_bytes),
439           __imm_addr(map_array_ro)
440         : __clobber_all);
441 }
442
443 SEC("socket")
444 __description("valid write map access into a write-only array 1")
445 __success __success_unpriv __retval(1)
446 __naked void a_write_only_array_1_1(void)
447 {
448         asm volatile ("                                 \
449         r1 = 0;                                         \
450         *(u64*)(r10 - 8) = r1;                          \
451         r2 = r10;                                       \
452         r2 += -8;                                       \
453         r1 = %[map_array_wo] ll;                        \
454         call %[bpf_map_lookup_elem];                    \
455         if r0 == 0 goto l0_%=;                          \
456         r1 = 42;                                        \
457         *(u64*)(r0 + 0) = r1;                           \
458 l0_%=:  r0 = 1;                                         \
459         exit;                                           \
460 "       :
461         : __imm(bpf_map_lookup_elem),
462           __imm_addr(map_array_wo)
463         : __clobber_all);
464 }
465
466 SEC("tc")
467 __description("valid write map access into a write-only array 2")
468 __success __retval(0)
469 __naked void a_write_only_array_2_1(void)
470 {
471         asm volatile ("                                 \
472         r6 = r1;                                        \
473         r1 = 0;                                         \
474         *(u64*)(r10 - 8) = r1;                          \
475         r2 = r10;                                       \
476         r2 += -8;                                       \
477         r1 = %[map_array_wo] ll;                        \
478         call %[bpf_map_lookup_elem];                    \
479         if r0 == 0 goto l0_%=;                          \
480         r1 = r6;                                        \
481         r2 = 0;                                         \
482         r3 = r0;                                        \
483         r4 = 8;                                         \
484         call %[bpf_skb_load_bytes];                     \
485 l0_%=:  exit;                                           \
486 "       :
487         : __imm(bpf_map_lookup_elem),
488           __imm(bpf_skb_load_bytes),
489           __imm_addr(map_array_wo)
490         : __clobber_all);
491 }
492
493 SEC("socket")
494 __description("invalid read map access into a write-only array 1")
495 __failure __msg("read from map forbidden")
496 __failure_unpriv
497 __naked void a_write_only_array_1_2(void)
498 {
499         asm volatile ("                                 \
500         r1 = 0;                                         \
501         *(u64*)(r10 - 8) = r1;                          \
502         r2 = r10;                                       \
503         r2 += -8;                                       \
504         r1 = %[map_array_wo] ll;                        \
505         call %[bpf_map_lookup_elem];                    \
506         if r0 == 0 goto l0_%=;                          \
507         r0 = *(u64*)(r0 + 0);                           \
508 l0_%=:  exit;                                           \
509 "       :
510         : __imm(bpf_map_lookup_elem),
511           __imm_addr(map_array_wo)
512         : __clobber_all);
513 }
514
515 SEC("tc")
516 __description("invalid read map access into a write-only array 2")
517 __failure __msg("read from map forbidden")
518 __naked void a_write_only_array_2_2(void)
519 {
520         asm volatile ("                                 \
521         r1 = 0;                                         \
522         *(u64*)(r10 - 8) = r1;                          \
523         r2 = r10;                                       \
524         r2 += -8;                                       \
525         r1 = %[map_array_wo] ll;                        \
526         call %[bpf_map_lookup_elem];                    \
527         if r0 == 0 goto l0_%=;                          \
528         r1 = r0;                                        \
529         r2 = 4;                                         \
530         r3 = 0;                                         \
531         r4 = 0;                                         \
532         r5 = 0;                                         \
533         call %[bpf_csum_diff];                          \
534 l0_%=:  exit;                                           \
535 "       :
536         : __imm(bpf_csum_diff),
537           __imm(bpf_map_lookup_elem),
538           __imm_addr(map_array_wo)
539         : __clobber_all);
540 }
541
542 SEC("socket")
543 __description("valid map access into an array using constant without nullness")
544 __success __retval(4) __log_level(2)
545 __msg("mark_precise: frame0: regs= stack=-8 before {{[0-9]}}: ({{[a-f0-9]+}}) *(u32 *)(r10 -8) = {{(1|r[0-9])}}")
546 unsigned int an_array_with_a_constant_no_nullness(void)
547 {
548         /* Need 8-byte alignment for spill tracking */
549         __u32 __attribute__((aligned(8))) key = 1;
550         struct test_val *val;
551
552         val = bpf_map_lookup_elem(&map_array, &key);
553         val->index = offsetof(struct test_val, foo);
554
555         return val->index;
556 }
557
558 SEC("socket")
559 __description("valid multiple map access into an array using constant without nullness")
560 __success __retval(8) __log_level(2)
561 __msg("mark_precise: frame0: regs= stack=-8 before {{[0-9]}}: ({{[a-f0-9]+}}) *(u32 *)(r10 -16) = {{(0|r[0-9])}}")
562 __msg("mark_precise: frame0: regs= stack=-8 before {{[0-9]}}: ({{[a-f0-9]+}}) *(u32 *)(r10 -8) = {{(1|r[0-9])}}")
563 unsigned int multiple_array_with_a_constant_no_nullness(void)
564 {
565         __u32 __attribute__((aligned(8))) key = 1;
566         __u32 __attribute__((aligned(8))) key2 = 0;
567         struct test_val *val, *val2;
568
569         val = bpf_map_lookup_elem(&map_array, &key);
570         val->index = offsetof(struct test_val, foo);
571
572         val2 = bpf_map_lookup_elem(&map_array, &key2);
573         val2->index = offsetof(struct test_val, foo);
574
575         return val->index + val2->index;
576 }
577
578 SEC("socket")
579 __description("valid map access into an array using natural aligned 32-bit constant 0 without nullness")
580 __success __retval(4)
581 unsigned int an_array_with_a_32bit_constant_0_no_nullness(void)
582 {
583         /* Unlike the above tests, 32-bit zeroing is precisely tracked even
584          * if writes are not aligned to BPF_REG_SIZE. This tests that our
585          * STACK_ZERO handling functions.
586          */
587         struct test_val *val;
588         __u32 key = 0;
589
590         val = bpf_map_lookup_elem(&map_array, &key);
591         val->index = offsetof(struct test_val, foo);
592
593         return val->index;
594 }
595
596 SEC("socket")
597 __description("valid map access into a pcpu array using constant without nullness")
598 __success __retval(4) __log_level(2)
599 __msg("mark_precise: frame0: regs= stack=-8 before {{[0-9]}}: ({{[a-f0-9]+}}) *(u32 *)(r10 -8) = {{(1|r[0-9])}}")
600 unsigned int a_pcpu_array_with_a_constant_no_nullness(void)
601 {
602         __u32 __attribute__((aligned(8))) key = 1;
603         struct test_val *val;
604
605         val = bpf_map_lookup_elem(&map_array_pcpu, &key);
606         val->index = offsetof(struct test_val, foo);
607
608         return val->index;
609 }
610
611 SEC("socket")
612 __description("invalid map access into an array using constant without nullness")
613 __failure __msg("R0 invalid mem access 'map_value_or_null'")
614 unsigned int an_array_with_a_constant_no_nullness_out_of_bounds(void)
615 {
616         /* Out of bounds */
617         __u32 __attribute__((aligned(8))) key = 3;
618         struct test_val *val;
619
620         val = bpf_map_lookup_elem(&map_array, &key);
621         val->index = offsetof(struct test_val, foo);
622
623         return val->index;
624 }
625
626 SEC("socket")
627 __description("invalid map access into an array using constant smaller than key_size")
628 __failure __msg("R0 invalid mem access 'map_value_or_null'")
629 unsigned int an_array_with_a_constant_too_small(void)
630 {
631         __u32 __attribute__((aligned(8))) key;
632         struct test_val *val;
633
634         /* Mark entire key as STACK_MISC */
635         bpf_probe_read_user(&key, sizeof(key), NULL);
636
637         /* Spilling only the bottom byte results in a tnum const of 1.
638          * We want to check that the verifier rejects it, as the spill is < 4B.
639          */
640         *(__u8 *)&key = 1;
641         val = bpf_map_lookup_elem(&map_array, &key);
642
643         /* Should fail, as verifier cannot prove in-bound lookup */
644         val->index = offsetof(struct test_val, foo);
645
646         return val->index;
647 }
648
649 SEC("socket")
650 __description("invalid map access into an array using constant larger than key_size")
651 __failure __msg("R0 invalid mem access 'map_value_or_null'")
652 unsigned int an_array_with_a_constant_too_big(void)
653 {
654         struct test_val *val;
655         __u64 key = 1;
656
657         /* Even if the constant value is < max_entries, if the spill size is
658          * larger than the key size, the set bits may not be where we expect them
659          * to be on different endian architectures.
660          */
661         val = bpf_map_lookup_elem(&map_array, &key);
662         val->index = offsetof(struct test_val, foo);
663
664         return val->index;
665 }
666
667 SEC("socket")
668 __description("invalid elided lookup using const and non-const key")
669 __failure __msg("R0 invalid mem access 'map_value_or_null'")
670 unsigned int mixed_const_and_non_const_key_lookup(void)
671 {
672         __u32 __attribute__((aligned(8))) key;
673         struct test_val *val;
674         __u32 rand;
675
676         rand = bpf_get_prandom_u32();
677         key = rand > 42 ? 1 : rand;
678         val = bpf_map_lookup_elem(&map_array, &key);
679
680         return val->index;
681 }
682
683 SEC("socket")
684 __failure __msg("invalid read from stack R2 off=4096 size=4")
685 __naked void key_lookup_at_invalid_fp(void)
686 {
687         asm volatile ("                                 \
688         r1 = %[map_array] ll;                           \
689         r2 = r10;                                       \
690         r2 += 4096;                                     \
691         call %[bpf_map_lookup_elem];                    \
692         r0 = *(u64*)(r0 + 0);                           \
693         exit;                                           \
694 "       :
695         : __imm(bpf_map_lookup_elem),
696           __imm_addr(map_array)
697         : __clobber_all);
698 }
699
700 volatile __u32 __attribute__((aligned(8))) global_key;
701
702 SEC("socket")
703 __description("invalid elided lookup using non-stack key")
704 __failure __msg("R0 invalid mem access 'map_value_or_null'")
705 unsigned int non_stack_key_lookup(void)
706 {
707         struct test_val *val;
708
709         global_key = 1;
710         val = bpf_map_lookup_elem(&map_array, (void *)&global_key);
711         val->index = offsetof(struct test_val, foo);
712
713         return val->index;
714 }
715
716 char _license[] SEC("license") = "GPL";
This page took 0.08049 seconds and 4 git commands to generate.