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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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/spin_lock.c */
  3 
  4 #include <linux/bpf.h>
  5 #include <bpf/bpf_helpers.h>
  6 #include "bpf_misc.h"
  7 
  8 struct val {
  9         int cnt;
 10         struct bpf_spin_lock l;
 11 };
 12 
 13 struct {
 14         __uint(type, BPF_MAP_TYPE_ARRAY);
 15         __uint(max_entries, 1);
 16         __type(key, int);
 17         __type(value, struct val);
 18 } map_spin_lock SEC(".maps");
 19 
 20 SEC("cgroup/skb")
 21 __description("spin_lock: test1 success")
 22 __success __failure_unpriv __msg_unpriv("")
 23 __retval(0)
 24 __naked void spin_lock_test1_success(void)
 25 {
 26         asm volatile ("                                 \
 27         r1 = 0;                                         \
 28         *(u32*)(r10 - 4) = r1;                          \
 29         r2 = r10;                                       \
 30         r2 += -4;                                       \
 31         r1 = %[map_spin_lock] ll;                       \
 32         call %[bpf_map_lookup_elem];                    \
 33         if r0 != 0 goto l0_%=;                          \
 34         exit;                                           \
 35 l0_%=:  r6 = r0;                                        \
 36         r1 = r0;                                        \
 37         r1 += 4;                                        \
 38         call %[bpf_spin_lock];                          \
 39         r1 = r6;                                        \
 40         r1 += 4;                                        \
 41         r0 = *(u32*)(r6 + 0);                           \
 42         call %[bpf_spin_unlock];                        \
 43         r0 = 0;                                         \
 44         exit;                                           \
 45 "       :
 46         : __imm(bpf_map_lookup_elem),
 47           __imm(bpf_spin_lock),
 48           __imm(bpf_spin_unlock),
 49           __imm_addr(map_spin_lock)
 50         : __clobber_all);
 51 }
 52 
 53 SEC("cgroup/skb")
 54 __description("spin_lock: test2 direct ld/st")
 55 __failure __msg("cannot be accessed directly")
 56 __failure_unpriv __msg_unpriv("")
 57 __naked void lock_test2_direct_ld_st(void)
 58 {
 59         asm volatile ("                                 \
 60         r1 = 0;                                         \
 61         *(u32*)(r10 - 4) = r1;                          \
 62         r2 = r10;                                       \
 63         r2 += -4;                                       \
 64         r1 = %[map_spin_lock] ll;                       \
 65         call %[bpf_map_lookup_elem];                    \
 66         if r0 != 0 goto l0_%=;                          \
 67         exit;                                           \
 68 l0_%=:  r6 = r0;                                        \
 69         r1 = r0;                                        \
 70         r1 += 4;                                        \
 71         call %[bpf_spin_lock];                          \
 72         r1 = r6;                                        \
 73         r1 += 4;                                        \
 74         r0 = *(u32*)(r1 + 0);                           \
 75         call %[bpf_spin_unlock];                        \
 76         r0 = 0;                                         \
 77         exit;                                           \
 78 "       :
 79         : __imm(bpf_map_lookup_elem),
 80           __imm(bpf_spin_lock),
 81           __imm(bpf_spin_unlock),
 82           __imm_addr(map_spin_lock)
 83         : __clobber_all);
 84 }
 85 
 86 SEC("cgroup/skb")
 87 __description("spin_lock: test3 direct ld/st")
 88 __failure __msg("cannot be accessed directly")
 89 __failure_unpriv __msg_unpriv("")
 90 __flag(BPF_F_ANY_ALIGNMENT)
 91 __naked void lock_test3_direct_ld_st(void)
 92 {
 93         asm volatile ("                                 \
 94         r1 = 0;                                         \
 95         *(u32*)(r10 - 4) = r1;                          \
 96         r2 = r10;                                       \
 97         r2 += -4;                                       \
 98         r1 = %[map_spin_lock] ll;                       \
 99         call %[bpf_map_lookup_elem];                    \
100         if r0 != 0 goto l0_%=;                          \
101         exit;                                           \
102 l0_%=:  r6 = r0;                                        \
103         r1 = r0;                                        \
104         r1 += 4;                                        \
105         call %[bpf_spin_lock];                          \
106         r1 = r6;                                        \
107         r1 += 4;                                        \
108         r0 = *(u32*)(r6 + 1);                           \
109         call %[bpf_spin_unlock];                        \
110         r0 = 0;                                         \
111         exit;                                           \
112 "       :
113         : __imm(bpf_map_lookup_elem),
114           __imm(bpf_spin_lock),
115           __imm(bpf_spin_unlock),
116           __imm_addr(map_spin_lock)
117         : __clobber_all);
118 }
119 
120 SEC("cgroup/skb")
121 __description("spin_lock: test4 direct ld/st")
122 __failure __msg("cannot be accessed directly")
123 __failure_unpriv __msg_unpriv("")
124 __flag(BPF_F_ANY_ALIGNMENT)
125 __naked void lock_test4_direct_ld_st(void)
126 {
127         asm volatile ("                                 \
128         r1 = 0;                                         \
129         *(u32*)(r10 - 4) = r1;                          \
130         r2 = r10;                                       \
131         r2 += -4;                                       \
132         r1 = %[map_spin_lock] ll;                       \
133         call %[bpf_map_lookup_elem];                    \
134         if r0 != 0 goto l0_%=;                          \
135         exit;                                           \
136 l0_%=:  r6 = r0;                                        \
137         r1 = r0;                                        \
138         r1 += 4;                                        \
139         call %[bpf_spin_lock];                          \
140         r1 = r6;                                        \
141         r1 += 4;                                        \
142         r0 = *(u16*)(r6 + 3);                           \
143         call %[bpf_spin_unlock];                        \
144         r0 = 0;                                         \
145         exit;                                           \
146 "       :
147         : __imm(bpf_map_lookup_elem),
148           __imm(bpf_spin_lock),
149           __imm(bpf_spin_unlock),
150           __imm_addr(map_spin_lock)
151         : __clobber_all);
152 }
153 
154 SEC("cgroup/skb")
155 __description("spin_lock: test5 call within a locked region")
156 __failure __msg("calls are not allowed")
157 __failure_unpriv __msg_unpriv("")
158 __naked void call_within_a_locked_region(void)
159 {
160         asm volatile ("                                 \
161         r1 = 0;                                         \
162         *(u32*)(r10 - 4) = r1;                          \
163         r2 = r10;                                       \
164         r2 += -4;                                       \
165         r1 = %[map_spin_lock] ll;                       \
166         call %[bpf_map_lookup_elem];                    \
167         if r0 != 0 goto l0_%=;                          \
168         exit;                                           \
169 l0_%=:  r6 = r0;                                        \
170         r1 = r0;                                        \
171         r1 += 4;                                        \
172         call %[bpf_spin_lock];                          \
173         call %[bpf_get_prandom_u32];                    \
174         r1 = r6;                                        \
175         r1 += 4;                                        \
176         call %[bpf_spin_unlock];                        \
177         r0 = 0;                                         \
178         exit;                                           \
179 "       :
180         : __imm(bpf_get_prandom_u32),
181           __imm(bpf_map_lookup_elem),
182           __imm(bpf_spin_lock),
183           __imm(bpf_spin_unlock),
184           __imm_addr(map_spin_lock)
185         : __clobber_all);
186 }
187 
188 SEC("cgroup/skb")
189 __description("spin_lock: test6 missing unlock")
190 __failure __msg("unlock is missing")
191 __failure_unpriv __msg_unpriv("")
192 __naked void spin_lock_test6_missing_unlock(void)
193 {
194         asm volatile ("                                 \
195         r1 = 0;                                         \
196         *(u32*)(r10 - 4) = r1;                          \
197         r2 = r10;                                       \
198         r2 += -4;                                       \
199         r1 = %[map_spin_lock] ll;                       \
200         call %[bpf_map_lookup_elem];                    \
201         if r0 != 0 goto l0_%=;                          \
202         exit;                                           \
203 l0_%=:  r6 = r0;                                        \
204         r1 = r0;                                        \
205         r1 += 4;                                        \
206         call %[bpf_spin_lock];                          \
207         r1 = r6;                                        \
208         r1 += 4;                                        \
209         r0 = *(u32*)(r6 + 0);                           \
210         if r0 != 0 goto l1_%=;                          \
211         call %[bpf_spin_unlock];                        \
212 l1_%=:  r0 = 0;                                         \
213         exit;                                           \
214 "       :
215         : __imm(bpf_map_lookup_elem),
216           __imm(bpf_spin_lock),
217           __imm(bpf_spin_unlock),
218           __imm_addr(map_spin_lock)
219         : __clobber_all);
220 }
221 
222 SEC("cgroup/skb")
223 __description("spin_lock: test7 unlock without lock")
224 __failure __msg("without taking a lock")
225 __failure_unpriv __msg_unpriv("")
226 __naked void lock_test7_unlock_without_lock(void)
227 {
228         asm volatile ("                                 \
229         r1 = 0;                                         \
230         *(u32*)(r10 - 4) = r1;                          \
231         r2 = r10;                                       \
232         r2 += -4;                                       \
233         r1 = %[map_spin_lock] ll;                       \
234         call %[bpf_map_lookup_elem];                    \
235         if r0 != 0 goto l0_%=;                          \
236         exit;                                           \
237 l0_%=:  r6 = r0;                                        \
238         r1 = r0;                                        \
239         r1 += 4;                                        \
240         if r1 != 0 goto l1_%=;                          \
241         call %[bpf_spin_lock];                          \
242 l1_%=:  r1 = r6;                                        \
243         r1 += 4;                                        \
244         r0 = *(u32*)(r6 + 0);                           \
245         call %[bpf_spin_unlock];                        \
246         r0 = 0;                                         \
247         exit;                                           \
248 "       :
249         : __imm(bpf_map_lookup_elem),
250           __imm(bpf_spin_lock),
251           __imm(bpf_spin_unlock),
252           __imm_addr(map_spin_lock)
253         : __clobber_all);
254 }
255 
256 SEC("cgroup/skb")
257 __description("spin_lock: test8 double lock")
258 __failure __msg("calls are not allowed")
259 __failure_unpriv __msg_unpriv("")
260 __naked void spin_lock_test8_double_lock(void)
261 {
262         asm volatile ("                                 \
263         r1 = 0;                                         \
264         *(u32*)(r10 - 4) = r1;                          \
265         r2 = r10;                                       \
266         r2 += -4;                                       \
267         r1 = %[map_spin_lock] ll;                       \
268         call %[bpf_map_lookup_elem];                    \
269         if r0 != 0 goto l0_%=;                          \
270         exit;                                           \
271 l0_%=:  r6 = r0;                                        \
272         r1 = r0;                                        \
273         r1 += 4;                                        \
274         call %[bpf_spin_lock];                          \
275         r1 = r6;                                        \
276         r1 += 4;                                        \
277         call %[bpf_spin_lock];                          \
278         r1 = r6;                                        \
279         r1 += 4;                                        \
280         r0 = *(u32*)(r6 + 0);                           \
281         call %[bpf_spin_unlock];                        \
282         r0 = 0;                                         \
283         exit;                                           \
284 "       :
285         : __imm(bpf_map_lookup_elem),
286           __imm(bpf_spin_lock),
287           __imm(bpf_spin_unlock),
288           __imm_addr(map_spin_lock)
289         : __clobber_all);
290 }
291 
292 SEC("cgroup/skb")
293 __description("spin_lock: test9 different lock")
294 __failure __msg("unlock of different lock")
295 __failure_unpriv __msg_unpriv("")
296 __naked void spin_lock_test9_different_lock(void)
297 {
298         asm volatile ("                                 \
299         r1 = 0;                                         \
300         *(u32*)(r10 - 4) = r1;                          \
301         r2 = r10;                                       \
302         r2 += -4;                                       \
303         r1 = %[map_spin_lock] ll;                       \
304         call %[bpf_map_lookup_elem];                    \
305         if r0 != 0 goto l0_%=;                          \
306         exit;                                           \
307 l0_%=:  r6 = r0;                                        \
308         r2 = r10;                                       \
309         r2 += -4;                                       \
310         r1 = %[map_spin_lock] ll;                       \
311         call %[bpf_map_lookup_elem];                    \
312         if r0 != 0 goto l1_%=;                          \
313         exit;                                           \
314 l1_%=:  r7 = r0;                                        \
315         r1 = r6;                                        \
316         r1 += 4;                                        \
317         call %[bpf_spin_lock];                          \
318         r1 = r7;                                        \
319         r1 += 4;                                        \
320         call %[bpf_spin_unlock];                        \
321         r0 = 0;                                         \
322         exit;                                           \
323 "       :
324         : __imm(bpf_map_lookup_elem),
325           __imm(bpf_spin_lock),
326           __imm(bpf_spin_unlock),
327           __imm_addr(map_spin_lock)
328         : __clobber_all);
329 }
330 
331 SEC("cgroup/skb")
332 __description("spin_lock: test10 lock in subprog without unlock")
333 __success
334 __failure_unpriv __msg_unpriv("")
335 __naked void lock_in_subprog_without_unlock(void)
336 {
337         asm volatile ("                                 \
338         r1 = 0;                                         \
339         *(u32*)(r10 - 4) = r1;                          \
340         r2 = r10;                                       \
341         r2 += -4;                                       \
342         r1 = %[map_spin_lock] ll;                       \
343         call %[bpf_map_lookup_elem];                    \
344         if r0 != 0 goto l0_%=;                          \
345         exit;                                           \
346 l0_%=:  r6 = r0;                                        \
347         r1 = r0;                                        \
348         r1 += 4;                                        \
349         call lock_in_subprog_without_unlock__1;         \
350         r1 = r6;                                        \
351         r1 += 4;                                        \
352         call %[bpf_spin_unlock];                        \
353         r0 = 1;                                         \
354         exit;                                           \
355 "       :
356         : __imm(bpf_map_lookup_elem),
357           __imm(bpf_spin_unlock),
358           __imm_addr(map_spin_lock)
359         : __clobber_all);
360 }
361 
362 static __naked __noinline __attribute__((used))
363 void lock_in_subprog_without_unlock__1(void)
364 {
365         asm volatile ("                                 \
366         call %[bpf_spin_lock];                          \
367         r0 = 0;                                         \
368         exit;                                           \
369 "       :
370         : __imm(bpf_spin_lock)
371         : __clobber_all);
372 }
373 
374 SEC("tc")
375 __description("spin_lock: test11 ld_abs under lock")
376 __failure __msg("inside bpf_spin_lock")
377 __naked void test11_ld_abs_under_lock(void)
378 {
379         asm volatile ("                                 \
380         r6 = r1;                                        \
381         r1 = 0;                                         \
382         *(u32*)(r10 - 4) = r1;                          \
383         r2 = r10;                                       \
384         r2 += -4;                                       \
385         r1 = %[map_spin_lock] ll;                       \
386         call %[bpf_map_lookup_elem];                    \
387         if r0 != 0 goto l0_%=;                          \
388         exit;                                           \
389 l0_%=:  r7 = r0;                                        \
390         r1 = r0;                                        \
391         r1 += 4;                                        \
392         call %[bpf_spin_lock];                          \
393         r0 = *(u8*)skb[0];                              \
394         r1 = r7;                                        \
395         r1 += 4;                                        \
396         call %[bpf_spin_unlock];                        \
397         r0 = 0;                                         \
398         exit;                                           \
399 "       :
400         : __imm(bpf_map_lookup_elem),
401           __imm(bpf_spin_lock),
402           __imm(bpf_spin_unlock),
403           __imm_addr(map_spin_lock)
404         : __clobber_all);
405 }
406 
407 SEC("tc")
408 __description("spin_lock: regsafe compare reg->id for map value")
409 __failure __msg("bpf_spin_unlock of different lock")
410 __flag(BPF_F_TEST_STATE_FREQ)
411 __naked void reg_id_for_map_value(void)
412 {
413         asm volatile ("                                 \
414         r6 = r1;                                        \
415         r6 = *(u32*)(r6 + %[__sk_buff_mark]);           \
416         r1 = %[map_spin_lock] ll;                       \
417         r9 = r1;                                        \
418         r2 = 0;                                         \
419         *(u32*)(r10 - 4) = r2;                          \
420         r2 = r10;                                       \
421         r2 += -4;                                       \
422         call %[bpf_map_lookup_elem];                    \
423         if r0 != 0 goto l0_%=;                          \
424         exit;                                           \
425 l0_%=:  r7 = r0;                                        \
426         r1 = r9;                                        \
427         r2 = r10;                                       \
428         r2 += -4;                                       \
429         call %[bpf_map_lookup_elem];                    \
430         if r0 != 0 goto l1_%=;                          \
431         exit;                                           \
432 l1_%=:  r8 = r0;                                        \
433         r1 = r7;                                        \
434         r1 += 4;                                        \
435         call %[bpf_spin_lock];                          \
436         if r6 == 0 goto l2_%=;                          \
437         goto l3_%=;                                     \
438 l2_%=:  r7 = r8;                                        \
439 l3_%=:  r1 = r7;                                        \
440         r1 += 4;                                        \
441         call %[bpf_spin_unlock];                        \
442         r0 = 0;                                         \
443         exit;                                           \
444 "       :
445         : __imm(bpf_map_lookup_elem),
446           __imm(bpf_spin_lock),
447           __imm(bpf_spin_unlock),
448           __imm_addr(map_spin_lock),
449           __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
450         : __clobber_all);
451 }
452 
453 /* Make sure that regsafe() compares ids for spin lock records using
454  * check_ids():
455  *  1: r9 = map_lookup_elem(...)  ; r9.id == 1
456  *  2: r8 = map_lookup_elem(...)  ; r8.id == 2
457  *  3: r7 = ktime_get_ns()
458  *  4: r6 = ktime_get_ns()
459  *  5: if r6 > r7 goto <9>
460  *  6: spin_lock(r8)
461  *  7: r9 = r8
462  *  8: goto <10>
463  *  9: spin_lock(r9)
464  * 10: spin_unlock(r9)             ; r9.id == 1 || r9.id == 2 and lock is active,
465  *                                 ; second visit to (10) should be considered safe
466  *                                 ; if check_ids() is used.
467  * 11: exit(0)
468  */
469 
470 SEC("cgroup/skb")
471 __description("spin_lock: regsafe() check_ids() similar id mappings")
472 __success __msg("29: safe")
473 __failure_unpriv __msg_unpriv("")
474 __log_level(2) __retval(0) __flag(BPF_F_TEST_STATE_FREQ)
475 __naked void check_ids_similar_id_mappings(void)
476 {
477         asm volatile ("                                 \
478         r1 = 0;                                         \
479         *(u32*)(r10 - 4) = r1;                          \
480         /* r9 = map_lookup_elem(...) */                 \
481         r2 = r10;                                       \
482         r2 += -4;                                       \
483         r1 = %[map_spin_lock] ll;                       \
484         call %[bpf_map_lookup_elem];                    \
485         if r0 == 0 goto l0_%=;                          \
486         r9 = r0;                                        \
487         /* r8 = map_lookup_elem(...) */                 \
488         r2 = r10;                                       \
489         r2 += -4;                                       \
490         r1 = %[map_spin_lock] ll;                       \
491         call %[bpf_map_lookup_elem];                    \
492         if r0 == 0 goto l1_%=;                          \
493         r8 = r0;                                        \
494         /* r7 = ktime_get_ns() */                       \
495         call %[bpf_ktime_get_ns];                       \
496         r7 = r0;                                        \
497         /* r6 = ktime_get_ns() */                       \
498         call %[bpf_ktime_get_ns];                       \
499         r6 = r0;                                        \
500         /* if r6 > r7 goto +5      ; no new information about the state is derived from\
501          *                         ; this check, thus produced verifier states differ\
502          *                         ; only in 'insn_idx' \
503          * spin_lock(r8)                                \
504          * r9 = r8                                      \
505          * goto unlock                                  \
506          */                                             \
507         if r6 > r7 goto l2_%=;                          \
508         r1 = r8;                                        \
509         r1 += 4;                                        \
510         call %[bpf_spin_lock];                          \
511         r9 = r8;                                        \
512         goto l3_%=;                                     \
513 l2_%=:  /* spin_lock(r9) */                             \
514         r1 = r9;                                        \
515         r1 += 4;                                        \
516         call %[bpf_spin_lock];                          \
517 l3_%=:  /* spin_unlock(r9) */                           \
518         r1 = r9;                                        \
519         r1 += 4;                                        \
520         call %[bpf_spin_unlock];                        \
521 l0_%=:  /* exit(0) */                                   \
522         r0 = 0;                                         \
523 l1_%=:  exit;                                           \
524 "       :
525         : __imm(bpf_ktime_get_ns),
526           __imm(bpf_map_lookup_elem),
527           __imm(bpf_spin_lock),
528           __imm(bpf_spin_unlock),
529           __imm_addr(map_spin_lock)
530         : __clobber_all);
531 }
532 
533 char _license[] SEC("license") = "GPL";
534 

~ [ 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