brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · ee5ddea Raw
365 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/regalloc.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include "bpf_misc.h"7 8#define MAX_ENTRIES 119 10struct test_val {11	unsigned int index;12	int foo[MAX_ENTRIES];13};14 15struct {16	__uint(type, BPF_MAP_TYPE_HASH);17	__uint(max_entries, 1);18	__type(key, long long);19	__type(value, struct test_val);20} map_hash_48b SEC(".maps");21 22SEC("tracepoint")23__description("regalloc basic")24__success __flag(BPF_F_ANY_ALIGNMENT)25__naked void regalloc_basic(void)26{27	asm volatile ("					\28	r6 = r1;					\29	r1 = 0;						\30	*(u64*)(r10 - 8) = r1;				\31	r2 = r10;					\32	r2 += -8;					\33	r1 = %[map_hash_48b] ll;			\34	call %[bpf_map_lookup_elem];			\35	if r0 == 0 goto l0_%=;				\36	r7 = r0;					\37	call %[bpf_get_prandom_u32];			\38	r2 = r0;					\39	if r0 s> 20 goto l0_%=;				\40	if r2 s< 0 goto l0_%=;				\41	r7 += r0;					\42	r7 += r2;					\43	r0 = *(u64*)(r7 + 0);				\44l0_%=:	exit;						\45"	:46	: __imm(bpf_get_prandom_u32),47	  __imm(bpf_map_lookup_elem),48	  __imm_addr(map_hash_48b)49	: __clobber_all);50}51 52SEC("tracepoint")53__description("regalloc negative")54__failure __msg("invalid access to map value, value_size=48 off=48 size=1")55__naked void regalloc_negative(void)56{57	asm volatile ("					\58	r6 = r1;					\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	r7 = r0;					\67	call %[bpf_get_prandom_u32];			\68	r2 = r0;					\69	if r0 s> 24 goto l0_%=;				\70	if r2 s< 0 goto l0_%=;				\71	r7 += r0;					\72	r7 += r2;					\73	r0 = *(u8*)(r7 + 0);				\74l0_%=:	exit;						\75"	:76	: __imm(bpf_get_prandom_u32),77	  __imm(bpf_map_lookup_elem),78	  __imm_addr(map_hash_48b)79	: __clobber_all);80}81 82SEC("tracepoint")83__description("regalloc src_reg mark")84__success __flag(BPF_F_ANY_ALIGNMENT)85__naked void regalloc_src_reg_mark(void)86{87	asm volatile ("					\88	r6 = r1;					\89	r1 = 0;						\90	*(u64*)(r10 - 8) = r1;				\91	r2 = r10;					\92	r2 += -8;					\93	r1 = %[map_hash_48b] ll;			\94	call %[bpf_map_lookup_elem];			\95	if r0 == 0 goto l0_%=;				\96	r7 = r0;					\97	call %[bpf_get_prandom_u32];			\98	r2 = r0;					\99	if r0 s> 20 goto l0_%=;				\100	r3 = 0;						\101	if r3 s>= r2 goto l0_%=;			\102	r7 += r0;					\103	r7 += r2;					\104	r0 = *(u64*)(r7 + 0);				\105l0_%=:	exit;						\106"	:107	: __imm(bpf_get_prandom_u32),108	  __imm(bpf_map_lookup_elem),109	  __imm_addr(map_hash_48b)110	: __clobber_all);111}112 113SEC("tracepoint")114__description("regalloc src_reg negative")115__failure __msg("invalid access to map value, value_size=48 off=44 size=8")116__flag(BPF_F_ANY_ALIGNMENT)117__naked void regalloc_src_reg_negative(void)118{119	asm volatile ("					\120	r6 = r1;					\121	r1 = 0;						\122	*(u64*)(r10 - 8) = r1;				\123	r2 = r10;					\124	r2 += -8;					\125	r1 = %[map_hash_48b] ll;			\126	call %[bpf_map_lookup_elem];			\127	if r0 == 0 goto l0_%=;				\128	r7 = r0;					\129	call %[bpf_get_prandom_u32];			\130	r2 = r0;					\131	if r0 s> 22 goto l0_%=;				\132	r3 = 0;						\133	if r3 s>= r2 goto l0_%=;			\134	r7 += r0;					\135	r7 += r2;					\136	r0 = *(u64*)(r7 + 0);				\137l0_%=:	exit;						\138"	:139	: __imm(bpf_get_prandom_u32),140	  __imm(bpf_map_lookup_elem),141	  __imm_addr(map_hash_48b)142	: __clobber_all);143}144 145SEC("tracepoint")146__description("regalloc and spill")147__success __flag(BPF_F_ANY_ALIGNMENT)148__naked void regalloc_and_spill(void)149{150	asm volatile ("					\151	r6 = r1;					\152	r1 = 0;						\153	*(u64*)(r10 - 8) = r1;				\154	r2 = r10;					\155	r2 += -8;					\156	r1 = %[map_hash_48b] ll;			\157	call %[bpf_map_lookup_elem];			\158	if r0 == 0 goto l0_%=;				\159	r7 = r0;					\160	call %[bpf_get_prandom_u32];			\161	r2 = r0;					\162	if r0 s> 20 goto l0_%=;				\163	/* r0 has upper bound that should propagate into r2 */\164	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\165	r0 = 0;						\166	r2 = 0;				/* clear r0 and r2 */\167	r3 = *(u64*)(r10 - 8);		/* fill r3 */	\168	if r0 s>= r3 goto l0_%=;			\169	/* r3 has lower and upper bounds */		\170	r7 += r3;					\171	r0 = *(u64*)(r7 + 0);				\172l0_%=:	exit;						\173"	:174	: __imm(bpf_get_prandom_u32),175	  __imm(bpf_map_lookup_elem),176	  __imm_addr(map_hash_48b)177	: __clobber_all);178}179 180SEC("tracepoint")181__description("regalloc and spill negative")182__failure __msg("invalid access to map value, value_size=48 off=48 size=8")183__flag(BPF_F_ANY_ALIGNMENT)184__naked void regalloc_and_spill_negative(void)185{186	asm volatile ("					\187	r6 = r1;					\188	r1 = 0;						\189	*(u64*)(r10 - 8) = r1;				\190	r2 = r10;					\191	r2 += -8;					\192	r1 = %[map_hash_48b] ll;			\193	call %[bpf_map_lookup_elem];			\194	if r0 == 0 goto l0_%=;				\195	r7 = r0;					\196	call %[bpf_get_prandom_u32];			\197	r2 = r0;					\198	if r0 s> 48 goto l0_%=;				\199	/* r0 has upper bound that should propagate into r2 */\200	*(u64*)(r10 - 8) = r2;		/* spill r2 */	\201	r0 = 0;						\202	r2 = 0;				/* clear r0 and r2 */\203	r3 = *(u64*)(r10 - 8);		/* fill r3 */\204	if r0 s>= r3 goto l0_%=;			\205	/* r3 has lower and upper bounds */		\206	r7 += r3;					\207	r0 = *(u64*)(r7 + 0);				\208l0_%=:	exit;						\209"	:210	: __imm(bpf_get_prandom_u32),211	  __imm(bpf_map_lookup_elem),212	  __imm_addr(map_hash_48b)213	: __clobber_all);214}215 216SEC("tracepoint")217__description("regalloc three regs")218__success __flag(BPF_F_ANY_ALIGNMENT)219__naked void regalloc_three_regs(void)220{221	asm volatile ("					\222	r6 = r1;					\223	r1 = 0;						\224	*(u64*)(r10 - 8) = r1;				\225	r2 = r10;					\226	r2 += -8;					\227	r1 = %[map_hash_48b] ll;			\228	call %[bpf_map_lookup_elem];			\229	if r0 == 0 goto l0_%=;				\230	r7 = r0;					\231	call %[bpf_get_prandom_u32];			\232	r2 = r0;					\233	r4 = r2;					\234	if r0 s> 12 goto l0_%=;				\235	if r2 s< 0 goto l0_%=;				\236	r7 += r0;					\237	r7 += r2;					\238	r7 += r4;					\239	r0 = *(u64*)(r7 + 0);				\240l0_%=:	exit;						\241"	:242	: __imm(bpf_get_prandom_u32),243	  __imm(bpf_map_lookup_elem),244	  __imm_addr(map_hash_48b)245	: __clobber_all);246}247 248SEC("tracepoint")249__description("regalloc after call")250__success __flag(BPF_F_ANY_ALIGNMENT)251__naked void regalloc_after_call(void)252{253	asm volatile ("					\254	r6 = r1;					\255	r1 = 0;						\256	*(u64*)(r10 - 8) = r1;				\257	r2 = r10;					\258	r2 += -8;					\259	r1 = %[map_hash_48b] ll;			\260	call %[bpf_map_lookup_elem];			\261	if r0 == 0 goto l0_%=;				\262	r7 = r0;					\263	call %[bpf_get_prandom_u32];			\264	r8 = r0;					\265	r9 = r0;					\266	call regalloc_after_call__1;			\267	if r8 s> 20 goto l0_%=;				\268	if r9 s< 0 goto l0_%=;				\269	r7 += r8;					\270	r7 += r9;					\271	r0 = *(u64*)(r7 + 0);				\272l0_%=:	exit;						\273"	:274	: __imm(bpf_get_prandom_u32),275	  __imm(bpf_map_lookup_elem),276	  __imm_addr(map_hash_48b)277	: __clobber_all);278}279 280static __naked __noinline __attribute__((used))281void regalloc_after_call__1(void)282{283	asm volatile ("					\284	r0 = 0;						\285	exit;						\286"	::: __clobber_all);287}288 289SEC("tracepoint")290__description("regalloc in callee")291__success __flag(BPF_F_ANY_ALIGNMENT)292__naked void regalloc_in_callee(void)293{294	asm volatile ("					\295	r6 = r1;					\296	r1 = 0;						\297	*(u64*)(r10 - 8) = r1;				\298	r2 = r10;					\299	r2 += -8;					\300	r1 = %[map_hash_48b] ll;			\301	call %[bpf_map_lookup_elem];			\302	if r0 == 0 goto l0_%=;				\303	r7 = r0;					\304	call %[bpf_get_prandom_u32];			\305	r1 = r0;					\306	r2 = r0;					\307	r3 = r7;					\308	call regalloc_in_callee__1;			\309l0_%=:	exit;						\310"	:311	: __imm(bpf_get_prandom_u32),312	  __imm(bpf_map_lookup_elem),313	  __imm_addr(map_hash_48b)314	: __clobber_all);315}316 317static __naked __noinline __attribute__((used))318void regalloc_in_callee__1(void)319{320	asm volatile ("					\321	if r1 s> 20 goto l0_%=;				\322	if r2 s< 0 goto l0_%=;				\323	r3 += r1;					\324	r3 += r2;					\325	r0 = *(u64*)(r3 + 0);				\326	exit;						\327l0_%=:	r0 = 0;						\328	exit;						\329"	::: __clobber_all);330}331 332SEC("tracepoint")333__description("regalloc, spill, JEQ")334__success335__naked void regalloc_spill_jeq(void)336{337	asm volatile ("					\338	r6 = r1;					\339	r1 = 0;						\340	*(u64*)(r10 - 8) = r1;				\341	r2 = r10;					\342	r2 += -8;					\343	r1 = %[map_hash_48b] ll;			\344	call %[bpf_map_lookup_elem];			\345	*(u64*)(r10 - 8) = r0;		/* spill r0 */	\346	if r0 == 0 goto l0_%=;				\347l0_%=:	/* The verifier will walk the rest twice with r0 == 0 and r0 == map_value */\348	call %[bpf_get_prandom_u32];			\349	r2 = r0;					\350	if r2 == 20 goto l1_%=;				\351l1_%=:	/* The verifier will walk the rest two more times with r0 == 20 and r0 == unknown */\352	r3 = *(u64*)(r10 - 8);		/* fill r3 with map_value */\353	if r3 == 0 goto l2_%=;		/* skip ldx if map_value == NULL */\354	/* Buggy verifier will think that r3 == 20 here */\355	r0 = *(u64*)(r3 + 0);		/* read from map_value */\356l2_%=:	exit;						\357"	:358	: __imm(bpf_get_prandom_u32),359	  __imm(bpf_map_lookup_elem),360	  __imm_addr(map_hash_48b)361	: __clobber_all);362}363 364char _license[] SEC("license") = "GPL";365