brintos

brintos / linux-shallow public Read only

0
0
Text · 16.9 KiB · 7ea535b Raw
727 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/unpriv.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include "../../../include/linux/filter.h"7#include "bpf_misc.h"8 9#define BPF_SK_LOOKUP(func) \10	/* struct bpf_sock_tuple tuple = {} */ \11	"r2 = 0;"			\12	"*(u32*)(r10 - 8) = r2;"	\13	"*(u64*)(r10 - 16) = r2;"	\14	"*(u64*)(r10 - 24) = r2;"	\15	"*(u64*)(r10 - 32) = r2;"	\16	"*(u64*)(r10 - 40) = r2;"	\17	"*(u64*)(r10 - 48) = r2;"	\18	/* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \19	"r2 = r10;"			\20	"r2 += -48;"			\21	"r3 = %[sizeof_bpf_sock_tuple];"\22	"r4 = 0;"			\23	"r5 = 0;"			\24	"call %[" #func "];"25 26struct {27	__uint(type, BPF_MAP_TYPE_HASH);28	__uint(max_entries, 1);29	__type(key, long long);30	__type(value, long long);31} map_hash_8b SEC(".maps");32 33void dummy_prog_42_socket(void);34void dummy_prog_24_socket(void);35void dummy_prog_loop1_socket(void);36 37struct {38	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);39	__uint(max_entries, 4);40	__uint(key_size, sizeof(int));41	__array(values, void (void));42} map_prog1_socket SEC(".maps") = {43	.values = {44		[0] = (void *)&dummy_prog_42_socket,45		[1] = (void *)&dummy_prog_loop1_socket,46		[2] = (void *)&dummy_prog_24_socket,47	},48};49 50SEC("socket")51__auxiliary __auxiliary_unpriv52__naked void dummy_prog_42_socket(void)53{54	asm volatile ("r0 = 42; exit;");55}56 57SEC("socket")58__auxiliary __auxiliary_unpriv59__naked void dummy_prog_24_socket(void)60{61	asm volatile ("r0 = 24; exit;");62}63 64SEC("socket")65__auxiliary __auxiliary_unpriv66__naked void dummy_prog_loop1_socket(void)67{68	asm volatile ("			\69	r3 = 1;				\70	r2 = %[map_prog1_socket] ll;	\71	call %[bpf_tail_call];		\72	r0 = 41;			\73	exit;				\74"	:75	: __imm(bpf_tail_call),76	  __imm_addr(map_prog1_socket)77	: __clobber_all);78}79 80SEC("socket")81__description("unpriv: return pointer")82__success __failure_unpriv __msg_unpriv("R0 leaks addr")83__retval(POINTER_VALUE)84__naked void unpriv_return_pointer(void)85{86	asm volatile ("					\87	r0 = r10;					\88	exit;						\89"	::: __clobber_all);90}91 92SEC("socket")93__description("unpriv: add const to pointer")94__success __success_unpriv __retval(0)95__naked void unpriv_add_const_to_pointer(void)96{97	asm volatile ("					\98	r1 += 8;					\99	r0 = 0;						\100	exit;						\101"	::: __clobber_all);102}103 104SEC("socket")105__description("unpriv: add pointer to pointer")106__failure __msg("R1 pointer += pointer")107__failure_unpriv108__naked void unpriv_add_pointer_to_pointer(void)109{110	asm volatile ("					\111	r1 += r10;					\112	r0 = 0;						\113	exit;						\114"	::: __clobber_all);115}116 117SEC("socket")118__description("unpriv: neg pointer")119__success __failure_unpriv __msg_unpriv("R1 pointer arithmetic")120__retval(0)121__naked void unpriv_neg_pointer(void)122{123	asm volatile ("					\124	r1 = -r1;					\125	r0 = 0;						\126	exit;						\127"	::: __clobber_all);128}129 130SEC("socket")131__description("unpriv: cmp pointer with const")132__success __failure_unpriv __msg_unpriv("R1 pointer comparison")133__retval(0)134__naked void unpriv_cmp_pointer_with_const(void)135{136	asm volatile ("					\137	if r1 == 0 goto l0_%=;				\138l0_%=:	r0 = 0;						\139	exit;						\140"	::: __clobber_all);141}142 143SEC("socket")144__description("unpriv: cmp pointer with pointer")145__success __failure_unpriv __msg_unpriv("R10 pointer comparison")146__retval(0)147__naked void unpriv_cmp_pointer_with_pointer(void)148{149	asm volatile ("					\150	if r1 == r10 goto l0_%=;			\151l0_%=:	r0 = 0;						\152	exit;						\153"	::: __clobber_all);154}155 156SEC("tracepoint")157__description("unpriv: check that printk is disallowed")158__success159__naked void check_that_printk_is_disallowed(void)160{161	asm volatile ("					\162	r1 = 0;						\163	*(u64*)(r10 - 8) = r1;				\164	r1 = r10;					\165	r1 += -8;					\166	r2 = 8;						\167	r3 = r1;					\168	call %[bpf_trace_printk];			\169	r0 = 0;						\170	exit;						\171"	:172	: __imm(bpf_trace_printk)173	: __clobber_all);174}175 176SEC("socket")177__description("unpriv: pass pointer to helper function")178__success __failure_unpriv __msg_unpriv("R4 leaks addr")179__retval(0)180__naked void pass_pointer_to_helper_function(void)181{182	asm volatile ("					\183	r1 = 0;						\184	*(u64*)(r10 - 8) = r1;				\185	r2 = r10;					\186	r2 += -8;					\187	r1 = %[map_hash_8b] ll;				\188	r3 = r2;					\189	r4 = r2;					\190	call %[bpf_map_update_elem];			\191	r0 = 0;						\192	exit;						\193"	:194	: __imm(bpf_map_update_elem),195	  __imm_addr(map_hash_8b)196	: __clobber_all);197}198 199SEC("socket")200__description("unpriv: indirectly pass pointer on stack to helper function")201__success __failure_unpriv202__msg_unpriv("invalid indirect read from stack R2 off -8+0 size 8")203__retval(0)204__naked void on_stack_to_helper_function(void)205{206	asm volatile ("					\207	*(u64*)(r10 - 8) = r10;				\208	r2 = r10;					\209	r2 += -8;					\210	r1 = %[map_hash_8b] ll;				\211	call %[bpf_map_lookup_elem];			\212	r0 = 0;						\213	exit;						\214"	:215	: __imm(bpf_map_lookup_elem),216	  __imm_addr(map_hash_8b)217	: __clobber_all);218}219 220SEC("socket")221__description("unpriv: mangle pointer on stack 1")222__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled")223__retval(0)224__naked void mangle_pointer_on_stack_1(void)225{226	asm volatile ("					\227	*(u64*)(r10 - 8) = r10;				\228	r0 = 0;						\229	*(u32*)(r10 - 8) = r0;				\230	r0 = 0;						\231	exit;						\232"	::: __clobber_all);233}234 235SEC("socket")236__description("unpriv: mangle pointer on stack 2")237__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled")238__retval(0)239__naked void mangle_pointer_on_stack_2(void)240{241	asm volatile ("					\242	*(u64*)(r10 - 8) = r10;				\243	r0 = 0;						\244	*(u8*)(r10 - 1) = r0;				\245	r0 = 0;						\246	exit;						\247"	::: __clobber_all);248}249 250SEC("socket")251__description("unpriv: read pointer from stack in small chunks")252__failure __msg("invalid size")253__failure_unpriv254__naked void from_stack_in_small_chunks(void)255{256	asm volatile ("					\257	*(u64*)(r10 - 8) = r10;				\258	r0 = *(u32*)(r10 - 8);				\259	r0 = 0;						\260	exit;						\261"	::: __clobber_all);262}263 264SEC("socket")265__description("unpriv: write pointer into ctx")266__failure __msg("invalid bpf_context access")267__failure_unpriv __msg_unpriv("R1 leaks addr")268__naked void unpriv_write_pointer_into_ctx(void)269{270	asm volatile ("					\271	*(u64*)(r1 + 0) = r1;				\272	r0 = 0;						\273	exit;						\274"	::: __clobber_all);275}276 277SEC("socket")278__description("unpriv: spill/fill of ctx")279__success __success_unpriv __retval(0)280__naked void unpriv_spill_fill_of_ctx(void)281{282	asm volatile ("					\283	r6 = r10;					\284	r6 += -8;					\285	*(u64*)(r6 + 0) = r1;				\286	r1 = *(u64*)(r6 + 0);				\287	r0 = 0;						\288	exit;						\289"	::: __clobber_all);290}291 292SEC("tc")293__description("unpriv: spill/fill of ctx 2")294__success __retval(0)295__naked void spill_fill_of_ctx_2(void)296{297	asm volatile ("					\298	r6 = r10;					\299	r6 += -8;					\300	*(u64*)(r6 + 0) = r1;				\301	r1 = *(u64*)(r6 + 0);				\302	call %[bpf_get_hash_recalc];			\303	r0 = 0;						\304	exit;						\305"	:306	: __imm(bpf_get_hash_recalc)307	: __clobber_all);308}309 310SEC("tc")311__description("unpriv: spill/fill of ctx 3")312__failure __msg("R1 type=fp expected=ctx")313__naked void spill_fill_of_ctx_3(void)314{315	asm volatile ("					\316	r6 = r10;					\317	r6 += -8;					\318	*(u64*)(r6 + 0) = r1;				\319	*(u64*)(r6 + 0) = r10;				\320	r1 = *(u64*)(r6 + 0);				\321	call %[bpf_get_hash_recalc];			\322	exit;						\323"	:324	: __imm(bpf_get_hash_recalc)325	: __clobber_all);326}327 328SEC("tc")329__description("unpriv: spill/fill of ctx 4")330__failure __msg("R1 type=scalar expected=ctx")331__naked void spill_fill_of_ctx_4(void)332{333	asm volatile ("					\334	r6 = r10;					\335	r6 += -8;					\336	*(u64*)(r6 + 0) = r1;				\337	r0 = 1;						\338	lock *(u64 *)(r10 - 8) += r0;			\339	r1 = *(u64*)(r6 + 0);				\340	call %[bpf_get_hash_recalc];			\341	exit;						\342"	:343	: __imm(bpf_get_hash_recalc)344	: __clobber_all);345}346 347SEC("tc")348__description("unpriv: spill/fill of different pointers stx")349__failure __msg("same insn cannot be used with different pointers")350__naked void fill_of_different_pointers_stx(void)351{352	asm volatile ("					\353	r3 = 42;					\354	r6 = r10;					\355	r6 += -8;					\356	if r1 == 0 goto l0_%=;				\357	r2 = r10;					\358	r2 += -16;					\359	*(u64*)(r6 + 0) = r2;				\360l0_%=:	if r1 != 0 goto l1_%=;				\361	*(u64*)(r6 + 0) = r1;				\362l1_%=:	r1 = *(u64*)(r6 + 0);				\363	*(u32*)(r1 + %[__sk_buff_mark]) = r3;		\364	r0 = 0;						\365	exit;						\366"	:367	: __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))368	: __clobber_all);369}370 371/* Same as above, but use BPF_ST_MEM to save 42372 * instead of BPF_STX_MEM.373 */374SEC("tc")375__description("unpriv: spill/fill of different pointers st")376__failure __msg("same insn cannot be used with different pointers")377__naked void fill_of_different_pointers_st(void)378{379	asm volatile ("					\380	r6 = r10;					\381	r6 += -8;					\382	if r1 == 0 goto l0_%=;				\383	r2 = r10;					\384	r2 += -16;					\385	*(u64*)(r6 + 0) = r2;				\386l0_%=:	if r1 != 0 goto l1_%=;				\387	*(u64*)(r6 + 0) = r1;				\388l1_%=:	r1 = *(u64*)(r6 + 0);				\389	.8byte %[st_mem];				\390	r0 = 0;						\391	exit;						\392"	:393	: __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),394	  __imm_insn(st_mem,395		     BPF_ST_MEM(BPF_W, BPF_REG_1, offsetof(struct __sk_buff, mark), 42))396	: __clobber_all);397}398 399SEC("tc")400__description("unpriv: spill/fill of different pointers stx - ctx and sock")401__failure __msg("type=ctx expected=sock")402__naked void pointers_stx_ctx_and_sock(void)403{404	asm volatile ("					\405	r8 = r1;					\406	/* struct bpf_sock *sock = bpf_sock_lookup(...); */\407"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)408"	r2 = r0;					\409	/* u64 foo; */					\410	/* void *target = &foo; */			\411	r6 = r10;					\412	r6 += -8;					\413	r1 = r8;					\414	/* if (skb == NULL) *target = sock; */		\415	if r1 == 0 goto l0_%=;				\416	*(u64*)(r6 + 0) = r2;				\417l0_%=:	/* else *target = skb; */			\418	if r1 != 0 goto l1_%=;				\419	*(u64*)(r6 + 0) = r1;				\420l1_%=:	/* struct __sk_buff *skb = *target; */		\421	r1 = *(u64*)(r6 + 0);				\422	/* skb->mark = 42; */				\423	r3 = 42;					\424	*(u32*)(r1 + %[__sk_buff_mark]) = r3;		\425	/* if (sk) bpf_sk_release(sk) */		\426	if r1 == 0 goto l2_%=;				\427	call %[bpf_sk_release];				\428l2_%=:	r0 = 0;						\429	exit;						\430"	:431	: __imm(bpf_sk_lookup_tcp),432	  __imm(bpf_sk_release),433	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),434	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))435	: __clobber_all);436}437 438SEC("tc")439__description("unpriv: spill/fill of different pointers stx - leak sock")440__failure441//.errstr = "same insn cannot be used with different pointers",442__msg("Unreleased reference")443__naked void different_pointers_stx_leak_sock(void)444{445	asm volatile ("					\446	r8 = r1;					\447	/* struct bpf_sock *sock = bpf_sock_lookup(...); */\448"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)449"	r2 = r0;					\450	/* u64 foo; */					\451	/* void *target = &foo; */			\452	r6 = r10;					\453	r6 += -8;					\454	r1 = r8;					\455	/* if (skb == NULL) *target = sock; */		\456	if r1 == 0 goto l0_%=;				\457	*(u64*)(r6 + 0) = r2;				\458l0_%=:	/* else *target = skb; */			\459	if r1 != 0 goto l1_%=;				\460	*(u64*)(r6 + 0) = r1;				\461l1_%=:	/* struct __sk_buff *skb = *target; */		\462	r1 = *(u64*)(r6 + 0);				\463	/* skb->mark = 42; */				\464	r3 = 42;					\465	*(u32*)(r1 + %[__sk_buff_mark]) = r3;		\466	exit;						\467"	:468	: __imm(bpf_sk_lookup_tcp),469	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),470	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))471	: __clobber_all);472}473 474SEC("tc")475__description("unpriv: spill/fill of different pointers stx - sock and ctx (read)")476__failure __msg("same insn cannot be used with different pointers")477__naked void stx_sock_and_ctx_read(void)478{479	asm volatile ("					\480	r8 = r1;					\481	/* struct bpf_sock *sock = bpf_sock_lookup(...); */\482"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)483"	r2 = r0;					\484	/* u64 foo; */					\485	/* void *target = &foo; */			\486	r6 = r10;					\487	r6 += -8;					\488	r1 = r8;					\489	/* if (skb) *target = skb */			\490	if r1 == 0 goto l0_%=;				\491	*(u64*)(r6 + 0) = r1;				\492l0_%=:	/* else *target = sock */			\493	if r1 != 0 goto l1_%=;				\494	*(u64*)(r6 + 0) = r2;				\495l1_%=:	/* struct bpf_sock *sk = *target; */		\496	r1 = *(u64*)(r6 + 0);				\497	/* if (sk) u32 foo = sk->mark; bpf_sk_release(sk); */\498	if r1 == 0 goto l2_%=;				\499	r3 = *(u32*)(r1 + %[bpf_sock_mark]);		\500	call %[bpf_sk_release];				\501l2_%=:	r0 = 0;						\502	exit;						\503"	:504	: __imm(bpf_sk_lookup_tcp),505	  __imm(bpf_sk_release),506	  __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)),507	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))508	: __clobber_all);509}510 511SEC("tc")512__description("unpriv: spill/fill of different pointers stx - sock and ctx (write)")513__failure514//.errstr = "same insn cannot be used with different pointers",515__msg("cannot write into sock")516__naked void stx_sock_and_ctx_write(void)517{518	asm volatile ("					\519	r8 = r1;					\520	/* struct bpf_sock *sock = bpf_sock_lookup(...); */\521"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)522"	r2 = r0;					\523	/* u64 foo; */					\524	/* void *target = &foo; */			\525	r6 = r10;					\526	r6 += -8;					\527	r1 = r8;					\528	/* if (skb) *target = skb */			\529	if r1 == 0 goto l0_%=;				\530	*(u64*)(r6 + 0) = r1;				\531l0_%=:	/* else *target = sock */			\532	if r1 != 0 goto l1_%=;				\533	*(u64*)(r6 + 0) = r2;				\534l1_%=:	/* struct bpf_sock *sk = *target; */		\535	r1 = *(u64*)(r6 + 0);				\536	/* if (sk) sk->mark = 42; bpf_sk_release(sk); */\537	if r1 == 0 goto l2_%=;				\538	r3 = 42;					\539	*(u32*)(r1 + %[bpf_sock_mark]) = r3;		\540	call %[bpf_sk_release];				\541l2_%=:	r0 = 0;						\542	exit;						\543"	:544	: __imm(bpf_sk_lookup_tcp),545	  __imm(bpf_sk_release),546	  __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)),547	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))548	: __clobber_all);549}550 551SEC("socket")552__description("unpriv: write pointer into map elem value")553__success __failure_unpriv __msg_unpriv("R0 leaks addr")554__retval(0)555__naked void pointer_into_map_elem_value(void)556{557	asm volatile ("					\558	r1 = 0;						\559	*(u64*)(r10 - 8) = r1;				\560	r2 = r10;					\561	r2 += -8;					\562	r1 = %[map_hash_8b] ll;				\563	call %[bpf_map_lookup_elem];			\564	if r0 == 0 goto l0_%=;				\565	*(u64*)(r0 + 0) = r0;				\566l0_%=:	exit;						\567"	:568	: __imm(bpf_map_lookup_elem),569	  __imm_addr(map_hash_8b)570	: __clobber_all);571}572 573SEC("socket")574__description("alu32: mov u32 const")575__success __failure_unpriv __msg_unpriv("R7 invalid mem access 'scalar'")576__retval(0)577__naked void alu32_mov_u32_const(void)578{579	asm volatile ("					\580	w7 = 0;						\581	w7 &= 1;					\582	w0 = w7;					\583	if r0 == 0 goto l0_%=;				\584	r0 = *(u64*)(r7 + 0);				\585l0_%=:	exit;						\586"	::: __clobber_all);587}588 589SEC("socket")590__description("unpriv: partial copy of pointer")591__success __failure_unpriv __msg_unpriv("R10 partial copy")592__retval(0)593__naked void unpriv_partial_copy_of_pointer(void)594{595	asm volatile ("					\596	w1 = w10;					\597	r0 = 0;						\598	exit;						\599"	::: __clobber_all);600}601 602SEC("socket")603__description("unpriv: pass pointer to tail_call")604__success __failure_unpriv __msg_unpriv("R3 leaks addr into helper")605__retval(0)606__naked void pass_pointer_to_tail_call(void)607{608	asm volatile ("					\609	r3 = r1;					\610	r2 = %[map_prog1_socket] ll;			\611	call %[bpf_tail_call];				\612	r0 = 0;						\613	exit;						\614"	:615	: __imm(bpf_tail_call),616	  __imm_addr(map_prog1_socket)617	: __clobber_all);618}619 620SEC("socket")621__description("unpriv: cmp map pointer with zero")622__success __failure_unpriv __msg_unpriv("R1 pointer comparison")623__retval(0)624__naked void cmp_map_pointer_with_zero(void)625{626	asm volatile ("					\627	r1 = 0;						\628	r1 = %[map_hash_8b] ll;				\629	if r1 == 0 goto l0_%=;				\630l0_%=:	r0 = 0;						\631	exit;						\632"	:633	: __imm_addr(map_hash_8b)634	: __clobber_all);635}636 637SEC("socket")638__description("unpriv: write into frame pointer")639__failure __msg("frame pointer is read only")640__failure_unpriv641__naked void unpriv_write_into_frame_pointer(void)642{643	asm volatile ("					\644	r10 = r1;					\645	r0 = 0;						\646	exit;						\647"	::: __clobber_all);648}649 650SEC("socket")651__description("unpriv: spill/fill frame pointer")652__failure __msg("frame pointer is read only")653__failure_unpriv654__naked void unpriv_spill_fill_frame_pointer(void)655{656	asm volatile ("					\657	r6 = r10;					\658	r6 += -8;					\659	*(u64*)(r6 + 0) = r10;				\660	r10 = *(u64*)(r6 + 0);				\661	r0 = 0;						\662	exit;						\663"	::: __clobber_all);664}665 666SEC("socket")667__description("unpriv: cmp of frame pointer")668__success __failure_unpriv __msg_unpriv("R10 pointer comparison")669__retval(0)670__naked void unpriv_cmp_of_frame_pointer(void)671{672	asm volatile ("					\673	if r10 == 0 goto l0_%=;				\674l0_%=:	r0 = 0;						\675	exit;						\676"	::: __clobber_all);677}678 679SEC("socket")680__description("unpriv: adding of fp, reg")681__success __failure_unpriv682__msg_unpriv("R1 stack pointer arithmetic goes out of range")683__retval(0)684__naked void unpriv_adding_of_fp_reg(void)685{686	asm volatile ("					\687	r0 = 0;						\688	r1 = 0;						\689	r1 += r10;					\690	*(u64*)(r1 - 8) = r0;				\691	exit;						\692"	::: __clobber_all);693}694 695SEC("socket")696__description("unpriv: adding of fp, imm")697__success __failure_unpriv698__msg_unpriv("R1 stack pointer arithmetic goes out of range")699__retval(0)700__naked void unpriv_adding_of_fp_imm(void)701{702	asm volatile ("					\703	r0 = 0;						\704	r1 = r10;					\705	r1 += 0;					\706	*(u64*)(r1 - 8) = r0;				\707	exit;						\708"	::: __clobber_all);709}710 711SEC("socket")712__description("unpriv: cmp of stack pointer")713__success __failure_unpriv __msg_unpriv("R2 pointer comparison")714__retval(0)715__naked void unpriv_cmp_of_stack_pointer(void)716{717	asm volatile ("					\718	r2 = r10;					\719	r2 += -8;					\720	if r2 == 0 goto l0_%=;				\721l0_%=:	r0 = 0;						\722	exit;						\723"	::: __clobber_all);724}725 726char _license[] SEC("license") = "GPL";727