brintos

brintos / linux-shallow public Read only

0
0
Text · 12.7 KiB · 95d7ecc Raw
530 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 119 10struct test_val {11	unsigned int index;12	int foo[MAX_ENTRIES];13};14 15struct {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 23struct {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 31struct {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 38SEC("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;				\54l0_%=:	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 62SEC("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;				\81l0_%=:	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 89SEC("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;				\109l0_%=:	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 118SEC("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;						\135l1_%=:	w2 = %[max_entries];				\136	if r2 s> r1 goto l2_%=;				\137	w1 = 0;						\138l2_%=:	w1 <<= 2;					\139	r0 += r1;					\140	r1 = %[test_val_foo];				\141	*(u64*)(r0 + 0) = r1;				\142l0_%=:	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 151SEC("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_unpriv155__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;			\167l0_%=:	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 176SEC("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_unpriv180__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;				\196l0_%=:	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 205SEC("socket")206__description("invalid map access into an array with a variable")207__failure208__msg("R0 unbounded memory access, make sure to bounds check any such access")209__failure_unpriv210__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;				\226l0_%=:	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 234SEC("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;						\253l1_%=:	w1 <<= 2;					\254	r0 += r1;					\255	r1 = %[test_val_foo];				\256	*(u64*)(r0 + 0) = r1;				\257l0_%=:	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 266SEC("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;						\285l1_%=:	w1 <<= 2;					\286	r0 += r1;					\287	r1 = %[test_val_foo];				\288	*(u64*)(r0 + 0) = r1;				\289l0_%=:	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 298SEC("socket")299__description("invalid map access into an array with a invalid max check")300__failure __msg("R0 pointer += pointer")301__failure_unpriv302__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]);		\323l0_%=:	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 331SEC("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);				\345l0_%=:	exit;						\346"	:347	: __imm(bpf_map_lookup_elem),348	  __imm_addr(map_array_ro)349	: __clobber_all);350}351 352SEC("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];				\371l0_%=:	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 380SEC("socket")381__description("invalid write map access into a read-only array 1")382__failure __msg("write into map forbidden")383__failure_unpriv384__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;				\396l0_%=:	exit;						\397"	:398	: __imm(bpf_map_lookup_elem),399	  __imm_addr(map_array_ro)400	: __clobber_all);401}402 403SEC("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];			\422l0_%=:	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 430SEC("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;				\445l0_%=:	r0 = 1;						\446	exit;						\447"	:448	: __imm(bpf_map_lookup_elem),449	  __imm_addr(map_array_wo)450	: __clobber_all);451}452 453SEC("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];			\472l0_%=:	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 480SEC("socket")481__description("invalid read map access into a write-only array 1")482__failure __msg("read from map forbidden")483__failure_unpriv484__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);				\495l0_%=:	exit;						\496"	:497	: __imm(bpf_map_lookup_elem),498	  __imm_addr(map_array_wo)499	: __clobber_all);500}501 502SEC("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];				\521l0_%=:	exit;						\522"	:523	: __imm(bpf_csum_diff),524	  __imm(bpf_map_lookup_elem),525	  __imm_addr(map_array_wo)526	: __clobber_all);527}528 529char _license[] SEC("license") = "GPL";530