~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/progs/verifier_array_access.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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_HASH);
 33         __uint(max_entries, 1);
 34         __type(key, long long);
 35         __type(value, struct test_val);
 36 } map_hash_48b SEC(".maps");
 37 
 38 SEC("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;                           \
 54 l0_%=:  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 
 62 SEC("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;                           \
 81 l0_%=:  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 
 89 SEC("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;                           \
109 l0_%=:  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 
118 SEC("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;                                         \
135 l1_%=:  w2 = %[max_entries];                            \
136         if r2 s> r1 goto l2_%=;                         \
137         w1 = 0;                                         \
138 l2_%=:  w1 <<= 2;                                       \
139         r0 += r1;                                       \
140         r1 = %[test_val_foo];                           \
141         *(u64*)(r0 + 0) = r1;                           \
142 l0_%=:  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 
151 SEC("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;                  \
167 l0_%=:  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 
176 SEC("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;                           \
196 l0_%=:  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 
205 SEC("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;                           \
226 l0_%=:  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 
234 SEC("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;                                         \
253 l1_%=:  w1 <<= 2;                                       \
254         r0 += r1;                                       \
255         r1 = %[test_val_foo];                           \
256         *(u64*)(r0 + 0) = r1;                           \
257 l0_%=:  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 
266 SEC("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;                                         \
285 l1_%=:  w1 <<= 2;                                       \
286         r0 += r1;                                       \
287         r1 = %[test_val_foo];                           \
288         *(u64*)(r0 + 0) = r1;                           \
289 l0_%=:  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 
298 SEC("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]);             \
323 l0_%=:  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 
331 SEC("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);                           \
345 l0_%=:  exit;                                           \
346 "       :
347         : __imm(bpf_map_lookup_elem),
348           __imm_addr(map_array_ro)
349         : __clobber_all);
350 }
351 
352 SEC("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];                          \
371 l0_%=:  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 
380 SEC("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;                           \
396 l0_%=:  exit;                                           \
397 "       :
398         : __imm(bpf_map_lookup_elem),
399           __imm_addr(map_array_ro)
400         : __clobber_all);
401 }
402 
403 SEC("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];                     \
422 l0_%=:  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 
430 SEC("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;                           \
445 l0_%=:  r0 = 1;                                         \
446         exit;                                           \
447 "       :
448         : __imm(bpf_map_lookup_elem),
449           __imm_addr(map_array_wo)
450         : __clobber_all);
451 }
452 
453 SEC("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];                     \
472 l0_%=:  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 
480 SEC("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);                           \
495 l0_%=:  exit;                                           \
496 "       :
497         : __imm(bpf_map_lookup_elem),
498           __imm_addr(map_array_wo)
499         : __clobber_all);
500 }
501 
502 SEC("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];                          \
521 l0_%=:  exit;                                           \
522 "       :
523         : __imm(bpf_csum_diff),
524           __imm(bpf_map_lookup_elem),
525           __imm_addr(map_array_wo)
526         : __clobber_all);
527 }
528 
529 char _license[] SEC("license") = "GPL";
530 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php