brintos

brintos / linux-shallow public Read only

0
0
Text · 12.1 KiB · fb316c0 Raw
534 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 8struct val {9	int cnt;10	struct bpf_spin_lock l;11};12 13struct {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 20SEC("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;						\35l0_%=:	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 53SEC("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;						\68l0_%=:	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 86SEC("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;						\102l0_%=:	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 120SEC("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;						\136l0_%=:	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 154SEC("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;						\169l0_%=:	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 188SEC("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;						\203l0_%=:	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];			\212l1_%=:	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 222SEC("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;						\237l0_%=:	r6 = r0;					\238	r1 = r0;					\239	r1 += 4;					\240	if r1 != 0 goto l1_%=;				\241	call %[bpf_spin_lock];				\242l1_%=:	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 256SEC("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;						\271l0_%=:	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 292SEC("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;						\307l0_%=:	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;						\314l1_%=:	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 331SEC("cgroup/skb")332__description("spin_lock: test10 lock in subprog without unlock")333__success334__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;						\346l0_%=:	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 362static __naked __noinline __attribute__((used))363void 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 374SEC("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;						\389l0_%=:	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 407SEC("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;						\425l0_%=:	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;						\432l1_%=:	r8 = r0;					\433	r1 = r7;					\434	r1 += 4;					\435	call %[bpf_spin_lock];				\436	if r6 == 0 goto l2_%=;				\437	goto l3_%=;					\438l2_%=:	r7 = r8;					\439l3_%=:	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 using454 * check_ids():455 *  1: r9 = map_lookup_elem(...)  ; r9.id == 1456 *  2: r8 = map_lookup_elem(...)  ; r8.id == 2457 *  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 = r8462 *  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 safe466 *                                 ; if check_ids() is used.467 * 11: exit(0)468 */469 470SEC("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_%=;					\513l2_%=:	/* spin_lock(r9) */				\514	r1 = r9;					\515	r1 += 4;					\516	call %[bpf_spin_lock];				\517l3_%=:	/* spin_unlock(r9) */				\518	r1 = r9;					\519	r1 += 4;					\520	call %[bpf_spin_unlock];			\521l0_%=:	/* exit(0) */					\522	r0 = 0;						\523l1_%=:	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 533char _license[] SEC("license") = "GPL";534