brintos

brintos / linux-shallow public Read only

0
0
Text · 37.3 KiB · c4c6da2 Raw
1496 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/ref_tracking.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 bpf_key {} __attribute__((preserve_access_index));27 28extern void bpf_key_put(struct bpf_key *key) __ksym;29extern struct bpf_key *bpf_lookup_system_key(__u64 id) __ksym;30extern struct bpf_key *bpf_lookup_user_key(__u32 serial, __u64 flags) __ksym;31 32/* BTF FUNC records are not generated for kfuncs referenced33 * from inline assembly. These records are necessary for34 * libbpf to link the program. The function below is a hack35 * to ensure that BTF FUNC records are generated.36 */37void __kfunc_btf_root(void)38{39	bpf_key_put(0);40	bpf_lookup_system_key(0);41	bpf_lookup_user_key(0, 0);42}43 44#define MAX_ENTRIES 1145 46struct test_val {47	unsigned int index;48	int foo[MAX_ENTRIES];49};50 51struct {52	__uint(type, BPF_MAP_TYPE_ARRAY);53	__uint(max_entries, 1);54	__type(key, int);55	__type(value, struct test_val);56} map_array_48b SEC(".maps");57 58struct {59	__uint(type, BPF_MAP_TYPE_RINGBUF);60	__uint(max_entries, 4096);61} map_ringbuf SEC(".maps");62 63void dummy_prog_42_tc(void);64void dummy_prog_24_tc(void);65void dummy_prog_loop1_tc(void);66 67struct {68	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);69	__uint(max_entries, 4);70	__uint(key_size, sizeof(int));71	__array(values, void (void));72} map_prog1_tc SEC(".maps") = {73	.values = {74		[0] = (void *)&dummy_prog_42_tc,75		[1] = (void *)&dummy_prog_loop1_tc,76		[2] = (void *)&dummy_prog_24_tc,77	},78};79 80SEC("tc")81__auxiliary82__naked void dummy_prog_42_tc(void)83{84	asm volatile ("r0 = 42; exit;");85}86 87SEC("tc")88__auxiliary89__naked void dummy_prog_24_tc(void)90{91	asm volatile ("r0 = 24; exit;");92}93 94SEC("tc")95__auxiliary96__naked void dummy_prog_loop1_tc(void)97{98	asm volatile ("			\99	r3 = 1;				\100	r2 = %[map_prog1_tc] ll;	\101	call %[bpf_tail_call];		\102	r0 = 41;			\103	exit;				\104"	:105	: __imm(bpf_tail_call),106	  __imm_addr(map_prog1_tc)107	: __clobber_all);108}109 110SEC("tc")111__description("reference tracking: leak potential reference")112__failure __msg("Unreleased reference")113__naked void reference_tracking_leak_potential_reference(void)114{115	asm volatile (116	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)117"	r6 = r0;		/* leak reference */	\118	exit;						\119"	:120	: __imm(bpf_sk_lookup_tcp),121	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))122	: __clobber_all);123}124 125SEC("tc")126__description("reference tracking: leak potential reference to sock_common")127__failure __msg("Unreleased reference")128__naked void potential_reference_to_sock_common_1(void)129{130	asm volatile (131	BPF_SK_LOOKUP(bpf_skc_lookup_tcp)132"	r6 = r0;		/* leak reference */	\133	exit;						\134"	:135	: __imm(bpf_skc_lookup_tcp),136	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))137	: __clobber_all);138}139 140SEC("tc")141__description("reference tracking: leak potential reference on stack")142__failure __msg("Unreleased reference")143__naked void leak_potential_reference_on_stack(void)144{145	asm volatile (146	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)147"	r4 = r10;					\148	r4 += -8;					\149	*(u64*)(r4 + 0) = r0;				\150	r0 = 0;						\151	exit;						\152"	:153	: __imm(bpf_sk_lookup_tcp),154	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))155	: __clobber_all);156}157 158SEC("tc")159__description("reference tracking: leak potential reference on stack 2")160__failure __msg("Unreleased reference")161__naked void potential_reference_on_stack_2(void)162{163	asm volatile (164	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)165"	r4 = r10;					\166	r4 += -8;					\167	*(u64*)(r4 + 0) = r0;				\168	r0 = 0;						\169	r1 = 0;						\170	*(u64*)(r4 + 0) = r1;				\171	exit;						\172"	:173	: __imm(bpf_sk_lookup_tcp),174	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))175	: __clobber_all);176}177 178SEC("tc")179__description("reference tracking: zero potential reference")180__failure __msg("Unreleased reference")181__naked void reference_tracking_zero_potential_reference(void)182{183	asm volatile (184	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)185"	r0 = 0;			/* leak reference */	\186	exit;						\187"	:188	: __imm(bpf_sk_lookup_tcp),189	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))190	: __clobber_all);191}192 193SEC("tc")194__description("reference tracking: zero potential reference to sock_common")195__failure __msg("Unreleased reference")196__naked void potential_reference_to_sock_common_2(void)197{198	asm volatile (199	BPF_SK_LOOKUP(bpf_skc_lookup_tcp)200"	r0 = 0;			/* leak reference */	\201	exit;						\202"	:203	: __imm(bpf_skc_lookup_tcp),204	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))205	: __clobber_all);206}207 208SEC("tc")209__description("reference tracking: copy and zero potential references")210__failure __msg("Unreleased reference")211__naked void copy_and_zero_potential_references(void)212{213	asm volatile (214	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)215"	r7 = r0;					\216	r0 = 0;						\217	r7 = 0;			/* leak reference */	\218	exit;						\219"	:220	: __imm(bpf_sk_lookup_tcp),221	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))222	: __clobber_all);223}224 225SEC("lsm.s/bpf")226__description("reference tracking: acquire/release user key reference")227__success228__naked void acquire_release_user_key_reference(void)229{230	asm volatile ("					\231	r1 = -3;					\232	r2 = 0;						\233	call %[bpf_lookup_user_key];			\234	if r0 == 0 goto l0_%=;				\235	r1 = r0;					\236	call %[bpf_key_put];				\237l0_%=:	r0 = 0;						\238	exit;						\239"	:240	: __imm(bpf_key_put),241	  __imm(bpf_lookup_user_key)242	: __clobber_all);243}244 245SEC("lsm.s/bpf")246__description("reference tracking: acquire/release system key reference")247__success248__naked void acquire_release_system_key_reference(void)249{250	asm volatile ("					\251	r1 = 1;						\252	call %[bpf_lookup_system_key];			\253	if r0 == 0 goto l0_%=;				\254	r1 = r0;					\255	call %[bpf_key_put];				\256l0_%=:	r0 = 0;						\257	exit;						\258"	:259	: __imm(bpf_key_put),260	  __imm(bpf_lookup_system_key)261	: __clobber_all);262}263 264SEC("lsm.s/bpf")265__description("reference tracking: release user key reference without check")266__failure __msg("Possibly NULL pointer passed to trusted arg0")267__naked void user_key_reference_without_check(void)268{269	asm volatile ("					\270	r1 = -3;					\271	r2 = 0;						\272	call %[bpf_lookup_user_key];			\273	r1 = r0;					\274	call %[bpf_key_put];				\275	r0 = 0;						\276	exit;						\277"	:278	: __imm(bpf_key_put),279	  __imm(bpf_lookup_user_key)280	: __clobber_all);281}282 283SEC("lsm.s/bpf")284__description("reference tracking: release system key reference without check")285__failure __msg("Possibly NULL pointer passed to trusted arg0")286__naked void system_key_reference_without_check(void)287{288	asm volatile ("					\289	r1 = 1;						\290	call %[bpf_lookup_system_key];			\291	r1 = r0;					\292	call %[bpf_key_put];				\293	r0 = 0;						\294	exit;						\295"	:296	: __imm(bpf_key_put),297	  __imm(bpf_lookup_system_key)298	: __clobber_all);299}300 301SEC("lsm.s/bpf")302__description("reference tracking: release with NULL key pointer")303__failure __msg("Possibly NULL pointer passed to trusted arg0")304__naked void release_with_null_key_pointer(void)305{306	asm volatile ("					\307	r1 = 0;						\308	call %[bpf_key_put];				\309	r0 = 0;						\310	exit;						\311"	:312	: __imm(bpf_key_put)313	: __clobber_all);314}315 316SEC("lsm.s/bpf")317__description("reference tracking: leak potential reference to user key")318__failure __msg("Unreleased reference")319__naked void potential_reference_to_user_key(void)320{321	asm volatile ("					\322	r1 = -3;					\323	r2 = 0;						\324	call %[bpf_lookup_user_key];			\325	exit;						\326"	:327	: __imm(bpf_lookup_user_key)328	: __clobber_all);329}330 331SEC("lsm.s/bpf")332__description("reference tracking: leak potential reference to system key")333__failure __msg("Unreleased reference")334__naked void potential_reference_to_system_key(void)335{336	asm volatile ("					\337	r1 = 1;						\338	call %[bpf_lookup_system_key];			\339	exit;						\340"	:341	: __imm(bpf_lookup_system_key)342	: __clobber_all);343}344 345SEC("tc")346__description("reference tracking: release reference without check")347__failure __msg("type=sock_or_null expected=sock")348__naked void tracking_release_reference_without_check(void)349{350	asm volatile (351	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)352"	/* reference in r0 may be NULL */		\353	r1 = r0;					\354	r2 = 0;						\355	call %[bpf_sk_release];				\356	exit;						\357"	:358	: __imm(bpf_sk_lookup_tcp),359	  __imm(bpf_sk_release),360	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))361	: __clobber_all);362}363 364SEC("tc")365__description("reference tracking: release reference to sock_common without check")366__failure __msg("type=sock_common_or_null expected=sock")367__naked void to_sock_common_without_check(void)368{369	asm volatile (370	BPF_SK_LOOKUP(bpf_skc_lookup_tcp)371"	/* reference in r0 may be NULL */		\372	r1 = r0;					\373	r2 = 0;						\374	call %[bpf_sk_release];				\375	exit;						\376"	:377	: __imm(bpf_sk_release),378	  __imm(bpf_skc_lookup_tcp),379	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))380	: __clobber_all);381}382 383SEC("tc")384__description("reference tracking: release reference")385__success __retval(0)386__naked void reference_tracking_release_reference(void)387{388	asm volatile (389	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)390"	r1 = r0;					\391	if r0 == 0 goto l0_%=;				\392	call %[bpf_sk_release];				\393l0_%=:	exit;						\394"	:395	: __imm(bpf_sk_lookup_tcp),396	  __imm(bpf_sk_release),397	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))398	: __clobber_all);399}400 401SEC("tc")402__description("reference tracking: release reference to sock_common")403__success __retval(0)404__naked void release_reference_to_sock_common(void)405{406	asm volatile (407	BPF_SK_LOOKUP(bpf_skc_lookup_tcp)408"	r1 = r0;					\409	if r0 == 0 goto l0_%=;				\410	call %[bpf_sk_release];				\411l0_%=:	exit;						\412"	:413	: __imm(bpf_sk_release),414	  __imm(bpf_skc_lookup_tcp),415	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))416	: __clobber_all);417}418 419SEC("tc")420__description("reference tracking: release reference 2")421__success __retval(0)422__naked void reference_tracking_release_reference_2(void)423{424	asm volatile (425	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)426"	r1 = r0;					\427	if r0 != 0 goto l0_%=;				\428	exit;						\429l0_%=:	call %[bpf_sk_release];				\430	exit;						\431"	:432	: __imm(bpf_sk_lookup_tcp),433	  __imm(bpf_sk_release),434	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))435	: __clobber_all);436}437 438SEC("tc")439__description("reference tracking: release reference twice")440__failure __msg("type=scalar expected=sock")441__naked void reference_tracking_release_reference_twice(void)442{443	asm volatile (444	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)445"	r1 = r0;					\446	r6 = r0;					\447	if r0 == 0 goto l0_%=;				\448	call %[bpf_sk_release];				\449l0_%=:	r1 = r6;					\450	call %[bpf_sk_release];				\451	exit;						\452"	:453	: __imm(bpf_sk_lookup_tcp),454	  __imm(bpf_sk_release),455	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))456	: __clobber_all);457}458 459SEC("tc")460__description("reference tracking: release reference twice inside branch")461__failure __msg("type=scalar expected=sock")462__naked void release_reference_twice_inside_branch(void)463{464	asm volatile (465	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)466"	r1 = r0;					\467	r6 = r0;					\468	if r0 == 0 goto l0_%=;		/* goto end */	\469	call %[bpf_sk_release];				\470	r1 = r6;					\471	call %[bpf_sk_release];				\472l0_%=:	exit;						\473"	:474	: __imm(bpf_sk_lookup_tcp),475	  __imm(bpf_sk_release),476	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))477	: __clobber_all);478}479 480SEC("tc")481__description("reference tracking: alloc, check, free in one subbranch")482__failure __msg("Unreleased reference")483__flag(BPF_F_ANY_ALIGNMENT)484__naked void check_free_in_one_subbranch(void)485{486	asm volatile ("					\487	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\488	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\489	r0 = r2;					\490	r0 += 16;					\491	/* if (offsetof(skb, mark) > data_len) exit; */	\492	if r0 <= r3 goto l0_%=;				\493	exit;						\494l0_%=:	r6 = *(u32*)(r2 + %[__sk_buff_mark]);		\495"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)496"	if r6 == 0 goto l1_%=;		/* mark == 0? */\497	/* Leak reference in R0 */			\498	exit;						\499l1_%=:	if r0 == 0 goto l2_%=;		/* sk NULL? */	\500	r1 = r0;					\501	call %[bpf_sk_release];				\502l2_%=:	exit;						\503"	:504	: __imm(bpf_sk_lookup_tcp),505	  __imm(bpf_sk_release),506	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),507	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),508	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),509	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))510	: __clobber_all);511}512 513SEC("tc")514__description("reference tracking: alloc, check, free in both subbranches")515__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)516__naked void check_free_in_both_subbranches(void)517{518	asm volatile ("					\519	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\520	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\521	r0 = r2;					\522	r0 += 16;					\523	/* if (offsetof(skb, mark) > data_len) exit; */	\524	if r0 <= r3 goto l0_%=;				\525	exit;						\526l0_%=:	r6 = *(u32*)(r2 + %[__sk_buff_mark]);		\527"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)528"	if r6 == 0 goto l1_%=;		/* mark == 0? */\529	if r0 == 0 goto l2_%=;		/* sk NULL? */	\530	r1 = r0;					\531	call %[bpf_sk_release];				\532l2_%=:	exit;						\533l1_%=:	if r0 == 0 goto l3_%=;		/* sk NULL? */	\534	r1 = r0;					\535	call %[bpf_sk_release];				\536l3_%=:	exit;						\537"	:538	: __imm(bpf_sk_lookup_tcp),539	  __imm(bpf_sk_release),540	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),541	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),542	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),543	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))544	: __clobber_all);545}546 547SEC("tc")548__description("reference tracking in call: free reference in subprog")549__success __retval(0)550__naked void call_free_reference_in_subprog(void)551{552	asm volatile (553	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)554"	r1 = r0;	/* unchecked reference */	\555	call call_free_reference_in_subprog__1;		\556	r0 = 0;						\557	exit;						\558"	:559	: __imm(bpf_sk_lookup_tcp),560	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))561	: __clobber_all);562}563 564static __naked __noinline __attribute__((used))565void call_free_reference_in_subprog__1(void)566{567	asm volatile ("					\568	/* subprog 1 */					\569	r2 = r1;					\570	if r2 == 0 goto l0_%=;				\571	call %[bpf_sk_release];				\572l0_%=:	exit;						\573"	:574	: __imm(bpf_sk_release)575	: __clobber_all);576}577 578SEC("tc")579__description("reference tracking in call: free reference in subprog and outside")580__failure __msg("type=scalar expected=sock")581__naked void reference_in_subprog_and_outside(void)582{583	asm volatile (584	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)585"	r1 = r0;	/* unchecked reference */	\586	r6 = r0;					\587	call reference_in_subprog_and_outside__1;	\588	r1 = r6;					\589	call %[bpf_sk_release];				\590	exit;						\591"	:592	: __imm(bpf_sk_lookup_tcp),593	  __imm(bpf_sk_release),594	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))595	: __clobber_all);596}597 598static __naked __noinline __attribute__((used))599void reference_in_subprog_and_outside__1(void)600{601	asm volatile ("					\602	/* subprog 1 */					\603	r2 = r1;					\604	if r2 == 0 goto l0_%=;				\605	call %[bpf_sk_release];				\606l0_%=:	exit;						\607"	:608	: __imm(bpf_sk_release)609	: __clobber_all);610}611 612SEC("tc")613__description("reference tracking in call: alloc & leak reference in subprog")614__failure __msg("Unreleased reference")615__naked void alloc_leak_reference_in_subprog(void)616{617	asm volatile ("					\618	r4 = r10;					\619	r4 += -8;					\620	call alloc_leak_reference_in_subprog__1;	\621	r1 = r0;					\622	r0 = 0;						\623	exit;						\624"	::: __clobber_all);625}626 627static __naked __noinline __attribute__((used))628void alloc_leak_reference_in_subprog__1(void)629{630	asm volatile ("					\631	/* subprog 1 */					\632	r6 = r4;					\633"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)634"	/* spill unchecked sk_ptr into stack of caller */\635	*(u64*)(r6 + 0) = r0;				\636	r1 = r0;					\637	exit;						\638"	:639	: __imm(bpf_sk_lookup_tcp),640	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))641	: __clobber_all);642}643 644SEC("tc")645__description("reference tracking in call: alloc in subprog, release outside")646__success __retval(POINTER_VALUE)647__naked void alloc_in_subprog_release_outside(void)648{649	asm volatile ("					\650	r4 = r10;					\651	call alloc_in_subprog_release_outside__1;	\652	r1 = r0;					\653	if r0 == 0 goto l0_%=;				\654	call %[bpf_sk_release];				\655l0_%=:	exit;						\656"	:657	: __imm(bpf_sk_release)658	: __clobber_all);659}660 661static __naked __noinline __attribute__((used))662void alloc_in_subprog_release_outside__1(void)663{664	asm volatile ("					\665	/* subprog 1 */					\666"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)667"	exit;				/* return sk */	\668"	:669	: __imm(bpf_sk_lookup_tcp),670	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))671	: __clobber_all);672}673 674SEC("tc")675__description("reference tracking in call: sk_ptr leak into caller stack")676__failure __msg("Unreleased reference")677__naked void ptr_leak_into_caller_stack(void)678{679	asm volatile ("					\680	r4 = r10;					\681	r4 += -8;					\682	call ptr_leak_into_caller_stack__1;		\683	r0 = 0;						\684	exit;						\685"	::: __clobber_all);686}687 688static __naked __noinline __attribute__((used))689void ptr_leak_into_caller_stack__1(void)690{691	asm volatile ("					\692	/* subprog 1 */					\693	r5 = r10;					\694	r5 += -8;					\695	*(u64*)(r5 + 0) = r4;				\696	call ptr_leak_into_caller_stack__2;		\697	/* spill unchecked sk_ptr into stack of caller */\698	r5 = r10;					\699	r5 += -8;					\700	r4 = *(u64*)(r5 + 0);				\701	*(u64*)(r4 + 0) = r0;				\702	exit;						\703"	::: __clobber_all);704}705 706static __naked __noinline __attribute__((used))707void ptr_leak_into_caller_stack__2(void)708{709	asm volatile ("					\710	/* subprog 2 */					\711"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)712"	exit;						\713"	:714	: __imm(bpf_sk_lookup_tcp),715	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))716	: __clobber_all);717}718 719SEC("tc")720__description("reference tracking in call: sk_ptr spill into caller stack")721__success __retval(0)722__naked void ptr_spill_into_caller_stack(void)723{724	asm volatile ("					\725	r4 = r10;					\726	r4 += -8;					\727	call ptr_spill_into_caller_stack__1;		\728	r0 = 0;						\729	exit;						\730"	::: __clobber_all);731}732 733static __naked __noinline __attribute__((used))734void ptr_spill_into_caller_stack__1(void)735{736	asm volatile ("					\737	/* subprog 1 */					\738	r5 = r10;					\739	r5 += -8;					\740	*(u64*)(r5 + 0) = r4;				\741	call ptr_spill_into_caller_stack__2;		\742	/* spill unchecked sk_ptr into stack of caller */\743	r5 = r10;					\744	r5 += -8;					\745	r4 = *(u64*)(r5 + 0);				\746	*(u64*)(r4 + 0) = r0;				\747	if r0 == 0 goto l0_%=;				\748	/* now the sk_ptr is verified, free the reference */\749	r1 = *(u64*)(r4 + 0);				\750	call %[bpf_sk_release];				\751l0_%=:	exit;						\752"	:753	: __imm(bpf_sk_release)754	: __clobber_all);755}756 757static __naked __noinline __attribute__((used))758void ptr_spill_into_caller_stack__2(void)759{760	asm volatile ("					\761	/* subprog 2 */					\762"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)763"	exit;						\764"	:765	: __imm(bpf_sk_lookup_tcp),766	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))767	: __clobber_all);768}769 770SEC("tc")771__description("reference tracking: allow LD_ABS")772__success __retval(0)773__naked void reference_tracking_allow_ld_abs(void)774{775	asm volatile ("					\776	r6 = r1;					\777"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)778"	r1 = r0;					\779	if r0 == 0 goto l0_%=;				\780	call %[bpf_sk_release];				\781l0_%=:	r0 = *(u8*)skb[0];				\782	r0 = *(u16*)skb[0];				\783	r0 = *(u32*)skb[0];				\784	exit;						\785"	:786	: __imm(bpf_sk_lookup_tcp),787	  __imm(bpf_sk_release),788	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))789	: __clobber_all);790}791 792SEC("tc")793__description("reference tracking: forbid LD_ABS while holding reference")794__failure __msg("BPF_LD_[ABS|IND] cannot be mixed with socket references")795__naked void ld_abs_while_holding_reference(void)796{797	asm volatile ("					\798	r6 = r1;					\799"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)800"	r0 = *(u8*)skb[0];				\801	r0 = *(u16*)skb[0];				\802	r0 = *(u32*)skb[0];				\803	r1 = r0;					\804	if r0 == 0 goto l0_%=;				\805	call %[bpf_sk_release];				\806l0_%=:	exit;						\807"	:808	: __imm(bpf_sk_lookup_tcp),809	  __imm(bpf_sk_release),810	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))811	: __clobber_all);812}813 814SEC("tc")815__description("reference tracking: allow LD_IND")816__success __retval(1)817__naked void reference_tracking_allow_ld_ind(void)818{819	asm volatile ("					\820	r6 = r1;					\821"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)822"	r1 = r0;					\823	if r0 == 0 goto l0_%=;				\824	call %[bpf_sk_release];				\825l0_%=:	r7 = 1;						\826	.8byte %[ld_ind];				\827	r0 = r7;					\828	exit;						\829"	:830	: __imm(bpf_sk_lookup_tcp),831	  __imm(bpf_sk_release),832	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)),833	  __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000))834	: __clobber_all);835}836 837SEC("tc")838__description("reference tracking: forbid LD_IND while holding reference")839__failure __msg("BPF_LD_[ABS|IND] cannot be mixed with socket references")840__naked void ld_ind_while_holding_reference(void)841{842	asm volatile ("					\843	r6 = r1;					\844"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)845"	r4 = r0;					\846	r7 = 1;						\847	.8byte %[ld_ind];				\848	r0 = r7;					\849	r1 = r4;					\850	if r1 == 0 goto l0_%=;				\851	call %[bpf_sk_release];				\852l0_%=:	exit;						\853"	:854	: __imm(bpf_sk_lookup_tcp),855	  __imm(bpf_sk_release),856	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)),857	  __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000))858	: __clobber_all);859}860 861SEC("tc")862__description("reference tracking: check reference or tail call")863__success __retval(0)864__naked void check_reference_or_tail_call(void)865{866	asm volatile ("					\867	r7 = r1;					\868"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)869"	/* if (sk) bpf_sk_release() */			\870	r1 = r0;					\871	if r1 != 0 goto l0_%=;				\872	/* bpf_tail_call() */				\873	r3 = 3;						\874	r2 = %[map_prog1_tc] ll;			\875	r1 = r7;					\876	call %[bpf_tail_call];				\877	r0 = 0;						\878	exit;						\879l0_%=:	call %[bpf_sk_release];				\880	exit;						\881"	:882	: __imm(bpf_sk_lookup_tcp),883	  __imm(bpf_sk_release),884	  __imm(bpf_tail_call),885	  __imm_addr(map_prog1_tc),886	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))887	: __clobber_all);888}889 890SEC("tc")891__description("reference tracking: release reference then tail call")892__success __retval(0)893__naked void release_reference_then_tail_call(void)894{895	asm volatile ("					\896	r7 = r1;					\897"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)898"	/* if (sk) bpf_sk_release() */			\899	r1 = r0;					\900	if r1 == 0 goto l0_%=;				\901	call %[bpf_sk_release];				\902l0_%=:	/* bpf_tail_call() */				\903	r3 = 3;						\904	r2 = %[map_prog1_tc] ll;			\905	r1 = r7;					\906	call %[bpf_tail_call];				\907	r0 = 0;						\908	exit;						\909"	:910	: __imm(bpf_sk_lookup_tcp),911	  __imm(bpf_sk_release),912	  __imm(bpf_tail_call),913	  __imm_addr(map_prog1_tc),914	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))915	: __clobber_all);916}917 918SEC("tc")919__description("reference tracking: leak possible reference over tail call")920__failure __msg("tail_call would lead to reference leak")921__naked void possible_reference_over_tail_call(void)922{923	asm volatile ("					\924	r7 = r1;					\925	/* Look up socket and store in REG_6 */		\926"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)927"	/* bpf_tail_call() */				\928	r6 = r0;					\929	r3 = 3;						\930	r2 = %[map_prog1_tc] ll;			\931	r1 = r7;					\932	call %[bpf_tail_call];				\933	r0 = 0;						\934	/* if (sk) bpf_sk_release() */			\935	r1 = r6;					\936	if r1 == 0 goto l0_%=;				\937	call %[bpf_sk_release];				\938l0_%=:	exit;						\939"	:940	: __imm(bpf_sk_lookup_tcp),941	  __imm(bpf_sk_release),942	  __imm(bpf_tail_call),943	  __imm_addr(map_prog1_tc),944	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))945	: __clobber_all);946}947 948SEC("tc")949__description("reference tracking: leak checked reference over tail call")950__failure __msg("tail_call would lead to reference leak")951__naked void checked_reference_over_tail_call(void)952{953	asm volatile ("					\954	r7 = r1;					\955	/* Look up socket and store in REG_6 */		\956"	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)957"	r6 = r0;					\958	/* if (!sk) goto end */				\959	if r0 == 0 goto l0_%=;				\960	/* bpf_tail_call() */				\961	r3 = 0;						\962	r2 = %[map_prog1_tc] ll;			\963	r1 = r7;					\964	call %[bpf_tail_call];				\965	r0 = 0;						\966	r1 = r6;					\967l0_%=:	call %[bpf_sk_release];				\968	exit;						\969"	:970	: __imm(bpf_sk_lookup_tcp),971	  __imm(bpf_sk_release),972	  __imm(bpf_tail_call),973	  __imm_addr(map_prog1_tc),974	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))975	: __clobber_all);976}977 978SEC("tc")979__description("reference tracking: mangle and release sock_or_null")980__failure __msg("R1 pointer arithmetic on sock_or_null prohibited")981__naked void and_release_sock_or_null(void)982{983	asm volatile (984	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)985"	r1 = r0;					\986	r1 += 5;					\987	if r0 == 0 goto l0_%=;				\988	call %[bpf_sk_release];				\989l0_%=:	exit;						\990"	:991	: __imm(bpf_sk_lookup_tcp),992	  __imm(bpf_sk_release),993	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))994	: __clobber_all);995}996 997SEC("tc")998__description("reference tracking: mangle and release sock")999__failure __msg("R1 pointer arithmetic on sock prohibited")1000__naked void tracking_mangle_and_release_sock(void)1001{1002	asm volatile (1003	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1004"	r1 = r0;					\1005	if r0 == 0 goto l0_%=;				\1006	r1 += 5;					\1007	call %[bpf_sk_release];				\1008l0_%=:	exit;						\1009"	:1010	: __imm(bpf_sk_lookup_tcp),1011	  __imm(bpf_sk_release),1012	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1013	: __clobber_all);1014}1015 1016SEC("tc")1017__description("reference tracking: access member")1018__success __retval(0)1019__naked void reference_tracking_access_member(void)1020{1021	asm volatile (1022	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1023"	r6 = r0;					\1024	if r0 == 0 goto l0_%=;				\1025	r2 = *(u32*)(r0 + 4);				\1026	r1 = r6;					\1027	call %[bpf_sk_release];				\1028l0_%=:	exit;						\1029"	:1030	: __imm(bpf_sk_lookup_tcp),1031	  __imm(bpf_sk_release),1032	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1033	: __clobber_all);1034}1035 1036SEC("tc")1037__description("reference tracking: write to member")1038__failure __msg("cannot write into sock")1039__naked void reference_tracking_write_to_member(void)1040{1041	asm volatile (1042	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1043"	r6 = r0;					\1044	if r0 == 0 goto l0_%=;				\1045	r1 = r6;					\1046	r2 = 42 ll;					\1047	*(u32*)(r1 + %[bpf_sock_mark]) = r2;		\1048	r1 = r6;					\1049l0_%=:	call %[bpf_sk_release];				\1050	r0 = 0 ll;					\1051	exit;						\1052"	:1053	: __imm(bpf_sk_lookup_tcp),1054	  __imm(bpf_sk_release),1055	  __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)),1056	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1057	: __clobber_all);1058}1059 1060SEC("tc")1061__description("reference tracking: invalid 64-bit access of member")1062__failure __msg("invalid sock access off=0 size=8")1063__naked void _64_bit_access_of_member(void)1064{1065	asm volatile (1066	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1067"	r6 = r0;					\1068	if r0 == 0 goto l0_%=;				\1069	r2 = *(u64*)(r0 + 0);				\1070	r1 = r6;					\1071	call %[bpf_sk_release];				\1072l0_%=:	exit;						\1073"	:1074	: __imm(bpf_sk_lookup_tcp),1075	  __imm(bpf_sk_release),1076	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1077	: __clobber_all);1078}1079 1080SEC("tc")1081__description("reference tracking: access after release")1082__failure __msg("!read_ok")1083__naked void reference_tracking_access_after_release(void)1084{1085	asm volatile (1086	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1087"	r1 = r0;					\1088	if r0 == 0 goto l0_%=;				\1089	call %[bpf_sk_release];				\1090	r2 = *(u32*)(r1 + 0);				\1091l0_%=:	exit;						\1092"	:1093	: __imm(bpf_sk_lookup_tcp),1094	  __imm(bpf_sk_release),1095	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1096	: __clobber_all);1097}1098 1099SEC("tc")1100__description("reference tracking: direct access for lookup")1101__success __retval(0)1102__naked void tracking_direct_access_for_lookup(void)1103{1104	asm volatile ("					\1105	/* Check that the packet is at least 64B long */\1106	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\1107	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\1108	r0 = r2;					\1109	r0 += 64;					\1110	if r0 > r3 goto l0_%=;				\1111	/* sk = sk_lookup_tcp(ctx, skb->data, ...) */	\1112	r3 = %[sizeof_bpf_sock_tuple];			\1113	r4 = 0;						\1114	r5 = 0;						\1115	call %[bpf_sk_lookup_tcp];			\1116	r6 = r0;					\1117	if r0 == 0 goto l0_%=;				\1118	r2 = *(u32*)(r0 + 4);				\1119	r1 = r6;					\1120	call %[bpf_sk_release];				\1121l0_%=:	exit;						\1122"	:1123	: __imm(bpf_sk_lookup_tcp),1124	  __imm(bpf_sk_release),1125	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),1126	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),1127	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1128	: __clobber_all);1129}1130 1131SEC("tc")1132__description("reference tracking: use ptr from bpf_tcp_sock() after release")1133__failure __msg("invalid mem access")1134__flag(BPF_F_ANY_ALIGNMENT)1135__naked void bpf_tcp_sock_after_release(void)1136{1137	asm volatile (1138	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1139"	if r0 != 0 goto l0_%=;				\1140	exit;						\1141l0_%=:	r6 = r0;					\1142	r1 = r0;					\1143	call %[bpf_tcp_sock];				\1144	if r0 != 0 goto l1_%=;				\1145	r1 = r6;					\1146	call %[bpf_sk_release];				\1147	exit;						\1148l1_%=:	r7 = r0;					\1149	r1 = r6;					\1150	call %[bpf_sk_release];				\1151	r0 = *(u32*)(r7 + %[bpf_tcp_sock_snd_cwnd]);	\1152	exit;						\1153"	:1154	: __imm(bpf_sk_lookup_tcp),1155	  __imm(bpf_sk_release),1156	  __imm(bpf_tcp_sock),1157	  __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)),1158	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1159	: __clobber_all);1160}1161 1162SEC("tc")1163__description("reference tracking: use ptr from bpf_sk_fullsock() after release")1164__failure __msg("invalid mem access")1165__flag(BPF_F_ANY_ALIGNMENT)1166__naked void bpf_sk_fullsock_after_release(void)1167{1168	asm volatile (1169	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1170"	if r0 != 0 goto l0_%=;				\1171	exit;						\1172l0_%=:	r6 = r0;					\1173	r1 = r0;					\1174	call %[bpf_sk_fullsock];			\1175	if r0 != 0 goto l1_%=;				\1176	r1 = r6;					\1177	call %[bpf_sk_release];				\1178	exit;						\1179l1_%=:	r7 = r0;					\1180	r1 = r6;					\1181	call %[bpf_sk_release];				\1182	r0 = *(u32*)(r7 + %[bpf_sock_type]);		\1183	exit;						\1184"	:1185	: __imm(bpf_sk_fullsock),1186	  __imm(bpf_sk_lookup_tcp),1187	  __imm(bpf_sk_release),1188	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1189	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1190	: __clobber_all);1191}1192 1193SEC("tc")1194__description("reference tracking: use ptr from bpf_sk_fullsock(tp) after release")1195__failure __msg("invalid mem access")1196__flag(BPF_F_ANY_ALIGNMENT)1197__naked void sk_fullsock_tp_after_release(void)1198{1199	asm volatile (1200	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1201"	if r0 != 0 goto l0_%=;				\1202	exit;						\1203l0_%=:	r6 = r0;					\1204	r1 = r0;					\1205	call %[bpf_tcp_sock];				\1206	if r0 != 0 goto l1_%=;				\1207	r1 = r6;					\1208	call %[bpf_sk_release];				\1209	exit;						\1210l1_%=:	r1 = r0;					\1211	call %[bpf_sk_fullsock];			\1212	r1 = r6;					\1213	r6 = r0;					\1214	call %[bpf_sk_release];				\1215	if r6 != 0 goto l2_%=;				\1216	exit;						\1217l2_%=:	r0 = *(u32*)(r6 + %[bpf_sock_type]);		\1218	exit;						\1219"	:1220	: __imm(bpf_sk_fullsock),1221	  __imm(bpf_sk_lookup_tcp),1222	  __imm(bpf_sk_release),1223	  __imm(bpf_tcp_sock),1224	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1225	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1226	: __clobber_all);1227}1228 1229SEC("tc")1230__description("reference tracking: use sk after bpf_sk_release(tp)")1231__failure __msg("invalid mem access")1232__flag(BPF_F_ANY_ALIGNMENT)1233__naked void after_bpf_sk_release_tp(void)1234{1235	asm volatile (1236	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1237"	if r0 != 0 goto l0_%=;				\1238	exit;						\1239l0_%=:	r6 = r0;					\1240	r1 = r0;					\1241	call %[bpf_tcp_sock];				\1242	if r0 != 0 goto l1_%=;				\1243	r1 = r6;					\1244	call %[bpf_sk_release];				\1245	exit;						\1246l1_%=:	r1 = r0;					\1247	call %[bpf_sk_release];				\1248	r0 = *(u32*)(r6 + %[bpf_sock_type]);		\1249	exit;						\1250"	:1251	: __imm(bpf_sk_lookup_tcp),1252	  __imm(bpf_sk_release),1253	  __imm(bpf_tcp_sock),1254	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1255	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1256	: __clobber_all);1257}1258 1259SEC("tc")1260__description("reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)")1261__success __retval(0)1262__naked void after_bpf_sk_release_sk(void)1263{1264	asm volatile (1265	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1266"	if r0 != 0 goto l0_%=;				\1267	exit;						\1268l0_%=:	r6 = r0;					\1269	r1 = r0;					\1270	call %[bpf_get_listener_sock];			\1271	if r0 != 0 goto l1_%=;				\1272	r1 = r6;					\1273	call %[bpf_sk_release];				\1274	exit;						\1275l1_%=:	r1 = r6;					\1276	r6 = r0;					\1277	call %[bpf_sk_release];				\1278	r0 = *(u32*)(r6 + %[bpf_sock_src_port]);	\1279	exit;						\1280"	:1281	: __imm(bpf_get_listener_sock),1282	  __imm(bpf_sk_lookup_tcp),1283	  __imm(bpf_sk_release),1284	  __imm_const(bpf_sock_src_port, offsetof(struct bpf_sock, src_port)),1285	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1286	: __clobber_all);1287}1288 1289SEC("tc")1290__description("reference tracking: bpf_sk_release(listen_sk)")1291__failure __msg("R1 must be referenced when passed to release function")1292__naked void bpf_sk_release_listen_sk(void)1293{1294	asm volatile (1295	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1296"	if r0 != 0 goto l0_%=;				\1297	exit;						\1298l0_%=:	r6 = r0;					\1299	r1 = r0;					\1300	call %[bpf_get_listener_sock];			\1301	if r0 != 0 goto l1_%=;				\1302	r1 = r6;					\1303	call %[bpf_sk_release];				\1304	exit;						\1305l1_%=:	r1 = r0;					\1306	call %[bpf_sk_release];				\1307	r0 = *(u32*)(r6 + %[bpf_sock_type]);		\1308	r1 = r6;					\1309	call %[bpf_sk_release];				\1310	exit;						\1311"	:1312	: __imm(bpf_get_listener_sock),1313	  __imm(bpf_sk_lookup_tcp),1314	  __imm(bpf_sk_release),1315	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1316	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1317	: __clobber_all);1318}1319 1320/* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */1321SEC("tc")1322__description("reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)")1323__failure __msg("invalid mem access")1324__naked void and_bpf_tcp_sock_sk(void)1325{1326	asm volatile (1327	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1328"	if r0 != 0 goto l0_%=;				\1329	exit;						\1330l0_%=:	r6 = r0;					\1331	r1 = r0;					\1332	call %[bpf_sk_fullsock];			\1333	r7 = r0;					\1334	r1 = r6;					\1335	call %[bpf_tcp_sock];				\1336	r8 = r0;					\1337	if r7 != 0 goto l1_%=;				\1338	r1 = r6;					\1339	call %[bpf_sk_release];				\1340	exit;						\1341l1_%=:	r0 = *(u32*)(r8 + %[bpf_tcp_sock_snd_cwnd]);	\1342	r1 = r6;					\1343	call %[bpf_sk_release];				\1344	exit;						\1345"	:1346	: __imm(bpf_sk_fullsock),1347	  __imm(bpf_sk_lookup_tcp),1348	  __imm(bpf_sk_release),1349	  __imm(bpf_tcp_sock),1350	  __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)),1351	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1352	: __clobber_all);1353}1354 1355SEC("tc")1356__description("reference tracking: branch tracking valid pointer null comparison")1357__success __retval(0)1358__naked void tracking_valid_pointer_null_comparison(void)1359{1360	asm volatile (1361	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1362"	r6 = r0;					\1363	r3 = 1;						\1364	if r6 != 0 goto l0_%=;				\1365	r3 = 0;						\1366l0_%=:	if r6 == 0 goto l1_%=;				\1367	r1 = r6;					\1368	call %[bpf_sk_release];				\1369l1_%=:	exit;						\1370"	:1371	: __imm(bpf_sk_lookup_tcp),1372	  __imm(bpf_sk_release),1373	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1374	: __clobber_all);1375}1376 1377SEC("tc")1378__description("reference tracking: branch tracking valid pointer value comparison")1379__failure __msg("Unreleased reference")1380__naked void tracking_valid_pointer_value_comparison(void)1381{1382	asm volatile (1383	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1384"	r6 = r0;					\1385	r3 = 1;						\1386	if r6 == 0 goto l0_%=;				\1387	r3 = 0;						\1388	if r6 == 1234 goto l0_%=;			\1389	r1 = r6;					\1390	call %[bpf_sk_release];				\1391l0_%=:	exit;						\1392"	:1393	: __imm(bpf_sk_lookup_tcp),1394	  __imm(bpf_sk_release),1395	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1396	: __clobber_all);1397}1398 1399SEC("tc")1400__description("reference tracking: bpf_sk_release(btf_tcp_sock)")1401__success1402__retval(0)1403__naked void sk_release_btf_tcp_sock(void)1404{1405	asm volatile (1406	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1407"	if r0 != 0 goto l0_%=;				\1408	exit;						\1409l0_%=:	r6 = r0;					\1410	r1 = r0;					\1411	call %[bpf_skc_to_tcp_sock];			\1412	if r0 != 0 goto l1_%=;				\1413	r1 = r6;					\1414	call %[bpf_sk_release];				\1415	exit;						\1416l1_%=:	r1 = r0;					\1417	call %[bpf_sk_release];				\1418	exit;						\1419"	:1420	: __imm(bpf_sk_lookup_tcp),1421	  __imm(bpf_sk_release),1422	  __imm(bpf_skc_to_tcp_sock),1423	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1424	: __clobber_all);1425}1426 1427SEC("tc")1428__description("reference tracking: use ptr from bpf_skc_to_tcp_sock() after release")1429__failure __msg("invalid mem access")1430__naked void to_tcp_sock_after_release(void)1431{1432	asm volatile (1433	BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1434"	if r0 != 0 goto l0_%=;				\1435	exit;						\1436l0_%=:	r6 = r0;					\1437	r1 = r0;					\1438	call %[bpf_skc_to_tcp_sock];			\1439	if r0 != 0 goto l1_%=;				\1440	r1 = r6;					\1441	call %[bpf_sk_release];				\1442	exit;						\1443l1_%=:	r7 = r0;					\1444	r1 = r6;					\1445	call %[bpf_sk_release];				\1446	r0 = *(u8*)(r7 + 0);				\1447	exit;						\1448"	:1449	: __imm(bpf_sk_lookup_tcp),1450	  __imm(bpf_sk_release),1451	  __imm(bpf_skc_to_tcp_sock),1452	  __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1453	: __clobber_all);1454}1455 1456SEC("socket")1457__description("reference tracking: try to leak released ptr reg")1458__success __failure_unpriv __msg_unpriv("R8 !read_ok")1459__retval(0)1460__naked void to_leak_released_ptr_reg(void)1461{1462	asm volatile ("					\1463	r0 = 0;						\1464	*(u32*)(r10 - 4) = r0;				\1465	r2 = r10;					\1466	r2 += -4;					\1467	r1 = %[map_array_48b] ll;			\1468	call %[bpf_map_lookup_elem];			\1469	if r0 != 0 goto l0_%=;				\1470	exit;						\1471l0_%=:	r9 = r0;					\1472	r0 = 0;						\1473	r1 = %[map_ringbuf] ll;				\1474	r2 = 8;						\1475	r3 = 0;						\1476	call %[bpf_ringbuf_reserve];			\1477	if r0 != 0 goto l1_%=;				\1478	exit;						\1479l1_%=:	r8 = r0;					\1480	r1 = r8;					\1481	r2 = 0;						\1482	call %[bpf_ringbuf_discard];			\1483	r0 = 0;						\1484	*(u64*)(r9 + 0) = r8;				\1485	exit;						\1486"	:1487	: __imm(bpf_map_lookup_elem),1488	  __imm(bpf_ringbuf_discard),1489	  __imm(bpf_ringbuf_reserve),1490	  __imm_addr(map_array_48b),1491	  __imm_addr(map_ringbuf)1492	: __clobber_all);1493}1494 1495char _license[] SEC("license") = "GPL";1496