brintos

brintos / linux-shallow public Read only

0
0
Text · 36.2 KiB · 8f36c9d Raw
1738 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2022 Facebook */3 4#include <errno.h>5#include <string.h>6#include <stdbool.h>7#include <linux/bpf.h>8#include <bpf/bpf_helpers.h>9#include <bpf/bpf_tracing.h>10#include <linux/if_ether.h>11#include "bpf_misc.h"12#include "bpf_kfuncs.h"13 14char _license[] SEC("license") = "GPL";15 16struct test_info {17	int x;18	struct bpf_dynptr ptr;19};20 21struct {22	__uint(type, BPF_MAP_TYPE_ARRAY);23	__uint(max_entries, 1);24	__type(key, __u32);25	__type(value, struct bpf_dynptr);26} array_map1 SEC(".maps");27 28struct {29	__uint(type, BPF_MAP_TYPE_ARRAY);30	__uint(max_entries, 1);31	__type(key, __u32);32	__type(value, struct test_info);33} array_map2 SEC(".maps");34 35struct {36	__uint(type, BPF_MAP_TYPE_ARRAY);37	__uint(max_entries, 1);38	__type(key, __u32);39	__type(value, __u32);40} array_map3 SEC(".maps");41 42struct {43	__uint(type, BPF_MAP_TYPE_ARRAY);44	__uint(max_entries, 1);45	__type(key, __u32);46	__type(value, __u64);47} array_map4 SEC(".maps");48 49struct sample {50	int pid;51	long value;52	char comm[16];53};54 55struct {56	__uint(type, BPF_MAP_TYPE_RINGBUF);57	__uint(max_entries, 4096);58} ringbuf SEC(".maps");59 60int err, val;61 62static int get_map_val_dynptr(struct bpf_dynptr *ptr)63{64	__u32 key = 0, *map_val;65 66	bpf_map_update_elem(&array_map3, &key, &val, 0);67 68	map_val = bpf_map_lookup_elem(&array_map3, &key);69	if (!map_val)70		return -ENOENT;71 72	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);73 74	return 0;75}76 77/* Every bpf_ringbuf_reserve_dynptr call must have a corresponding78 * bpf_ringbuf_submit/discard_dynptr call79 */80SEC("?raw_tp")81__failure __msg("Unreleased reference id=2")82int ringbuf_missing_release1(void *ctx)83{84	struct bpf_dynptr ptr = {};85 86	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);87 88	/* missing a call to bpf_ringbuf_discard/submit_dynptr */89 90	return 0;91}92 93SEC("?raw_tp")94__failure __msg("Unreleased reference id=4")95int ringbuf_missing_release2(void *ctx)96{97	struct bpf_dynptr ptr1, ptr2;98	struct sample *sample;99 100	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);101	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);102 103	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));104	if (!sample) {105		bpf_ringbuf_discard_dynptr(&ptr1, 0);106		bpf_ringbuf_discard_dynptr(&ptr2, 0);107		return 0;108	}109 110	bpf_ringbuf_submit_dynptr(&ptr1, 0);111 112	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */113 114	return 0;115}116 117static int missing_release_callback_fn(__u32 index, void *data)118{119	struct bpf_dynptr ptr;120 121	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);122 123	/* missing a call to bpf_ringbuf_discard/submit_dynptr */124 125	return 0;126}127 128/* Any dynptr initialized within a callback must have bpf_dynptr_put called */129SEC("?raw_tp")130__failure __msg("Unreleased reference id")131int ringbuf_missing_release_callback(void *ctx)132{133	bpf_loop(10, missing_release_callback_fn, NULL, 0);134	return 0;135}136 137/* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */138SEC("?raw_tp")139__failure __msg("arg 1 is an unacquired reference")140int ringbuf_release_uninit_dynptr(void *ctx)141{142	struct bpf_dynptr ptr;143 144	/* this should fail */145	bpf_ringbuf_submit_dynptr(&ptr, 0);146 147	return 0;148}149 150/* A dynptr can't be used after it has been invalidated */151SEC("?raw_tp")152__failure __msg("Expected an initialized dynptr as arg #3")153int use_after_invalid(void *ctx)154{155	struct bpf_dynptr ptr;156	char read_data[64];157 158	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);159 160	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);161 162	bpf_ringbuf_submit_dynptr(&ptr, 0);163 164	/* this should fail */165	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);166 167	return 0;168}169 170/* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */171SEC("?raw_tp")172__failure __msg("type=mem expected=ringbuf_mem")173int ringbuf_invalid_api(void *ctx)174{175	struct bpf_dynptr ptr;176	struct sample *sample;177 178	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);179	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));180	if (!sample)181		goto done;182 183	sample->pid = 123;184 185	/* invalid API use. need to use dynptr API to submit/discard */186	bpf_ringbuf_submit(sample, 0);187 188done:189	bpf_ringbuf_discard_dynptr(&ptr, 0);190	return 0;191}192 193/* Can't add a dynptr to a map */194SEC("?raw_tp")195__failure __msg("invalid indirect read from stack")196int add_dynptr_to_map1(void *ctx)197{198	struct bpf_dynptr ptr;199	int key = 0;200 201	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);202 203	/* this should fail */204	bpf_map_update_elem(&array_map1, &key, &ptr, 0);205 206	bpf_ringbuf_submit_dynptr(&ptr, 0);207 208	return 0;209}210 211/* Can't add a struct with an embedded dynptr to a map */212SEC("?raw_tp")213__failure __msg("invalid indirect read from stack")214int add_dynptr_to_map2(void *ctx)215{216	struct test_info x;217	int key = 0;218 219	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);220 221	/* this should fail */222	bpf_map_update_elem(&array_map2, &key, &x, 0);223 224	bpf_ringbuf_submit_dynptr(&x.ptr, 0);225 226	return 0;227}228 229/* A data slice can't be accessed out of bounds */230SEC("?raw_tp")231__failure __msg("value is outside of the allowed memory range")232int data_slice_out_of_bounds_ringbuf(void *ctx)233{234	struct bpf_dynptr ptr;235	void *data;236 237	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);238 239	data  = bpf_dynptr_data(&ptr, 0, 8);240	if (!data)241		goto done;242 243	/* can't index out of bounds of the data slice */244	val = *((char *)data + 8);245 246done:247	bpf_ringbuf_submit_dynptr(&ptr, 0);248	return 0;249}250 251/* A data slice can't be accessed out of bounds */252SEC("?tc")253__failure __msg("value is outside of the allowed memory range")254int data_slice_out_of_bounds_skb(struct __sk_buff *skb)255{256	struct bpf_dynptr ptr;257	struct ethhdr *hdr;258	char buffer[sizeof(*hdr)] = {};259 260	bpf_dynptr_from_skb(skb, 0, &ptr);261 262	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));263	if (!hdr)264		return SK_DROP;265 266	/* this should fail */267	*(__u8*)(hdr + 1) = 1;268 269	return SK_PASS;270}271 272SEC("?raw_tp")273__failure __msg("value is outside of the allowed memory range")274int data_slice_out_of_bounds_map_value(void *ctx)275{276	__u32 map_val;277	struct bpf_dynptr ptr;278	void *data;279 280	get_map_val_dynptr(&ptr);281 282	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));283	if (!data)284		return 0;285 286	/* can't index out of bounds of the data slice */287	val = *((char *)data + (sizeof(map_val) + 1));288 289	return 0;290}291 292/* A data slice can't be used after it has been released */293SEC("?raw_tp")294__failure __msg("invalid mem access 'scalar'")295int data_slice_use_after_release1(void *ctx)296{297	struct bpf_dynptr ptr;298	struct sample *sample;299 300	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);301	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));302	if (!sample)303		goto done;304 305	sample->pid = 123;306 307	bpf_ringbuf_submit_dynptr(&ptr, 0);308 309	/* this should fail */310	val = sample->pid;311 312	return 0;313 314done:315	bpf_ringbuf_discard_dynptr(&ptr, 0);316	return 0;317}318 319/* A data slice can't be used after it has been released.320 *321 * This tests the case where the data slice tracks a dynptr (ptr2)322 * that is at a non-zero offset from the frame pointer (ptr1 is at fp,323 * ptr2 is at fp - 16).324 */325SEC("?raw_tp")326__failure __msg("invalid mem access 'scalar'")327int data_slice_use_after_release2(void *ctx)328{329	struct bpf_dynptr ptr1, ptr2;330	struct sample *sample;331 332	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);333	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);334 335	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));336	if (!sample)337		goto done;338 339	sample->pid = 23;340 341	bpf_ringbuf_submit_dynptr(&ptr2, 0);342 343	/* this should fail */344	sample->pid = 23;345 346	bpf_ringbuf_submit_dynptr(&ptr1, 0);347 348	return 0;349 350done:351	bpf_ringbuf_discard_dynptr(&ptr2, 0);352	bpf_ringbuf_discard_dynptr(&ptr1, 0);353	return 0;354}355 356/* A data slice must be first checked for NULL */357SEC("?raw_tp")358__failure __msg("invalid mem access 'mem_or_null'")359int data_slice_missing_null_check1(void *ctx)360{361	struct bpf_dynptr ptr;362	void *data;363 364	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);365 366	data  = bpf_dynptr_data(&ptr, 0, 8);367 368	/* missing if (!data) check */369 370	/* this should fail */371	*(__u8 *)data = 3;372 373	bpf_ringbuf_submit_dynptr(&ptr, 0);374	return 0;375}376 377/* A data slice can't be dereferenced if it wasn't checked for null */378SEC("?raw_tp")379__failure __msg("invalid mem access 'mem_or_null'")380int data_slice_missing_null_check2(void *ctx)381{382	struct bpf_dynptr ptr;383	__u64 *data1, *data2;384 385	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);386 387	data1 = bpf_dynptr_data(&ptr, 0, 8);388	data2 = bpf_dynptr_data(&ptr, 0, 8);389	if (data1)390		/* this should fail */391		*data2 = 3;392 393	bpf_ringbuf_discard_dynptr(&ptr, 0);394	return 0;395}396 397/* Can't pass in a dynptr as an arg to a helper function that doesn't take in a398 * dynptr argument399 */400SEC("?raw_tp")401__failure __msg("invalid indirect read from stack")402int invalid_helper1(void *ctx)403{404	struct bpf_dynptr ptr;405 406	get_map_val_dynptr(&ptr);407 408	/* this should fail */409	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");410 411	return 0;412}413 414/* A dynptr can't be passed into a helper function at a non-zero offset */415SEC("?raw_tp")416__failure __msg("cannot pass in dynptr at an offset=-8")417int invalid_helper2(void *ctx)418{419	struct bpf_dynptr ptr;420	char read_data[64];421 422	get_map_val_dynptr(&ptr);423 424	/* this should fail */425	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);426	return 0;427}428 429/* A bpf_dynptr is invalidated if it's been written into */430SEC("?raw_tp")431__failure __msg("Expected an initialized dynptr as arg #1")432int invalid_write1(void *ctx)433{434	struct bpf_dynptr ptr;435	void *data;436	__u8 x = 0;437 438	get_map_val_dynptr(&ptr);439 440	memcpy(&ptr, &x, sizeof(x));441 442	/* this should fail */443	data = bpf_dynptr_data(&ptr, 0, 1);444	__sink(data);445 446	return 0;447}448 449/*450 * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed451 * offset452 */453SEC("?raw_tp")454__failure __msg("cannot overwrite referenced dynptr")455int invalid_write2(void *ctx)456{457	struct bpf_dynptr ptr;458	char read_data[64];459	__u8 x = 0;460 461	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);462 463	memcpy((void *)&ptr + 8, &x, sizeof(x));464 465	/* this should fail */466	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);467 468	bpf_ringbuf_submit_dynptr(&ptr, 0);469 470	return 0;471}472 473/*474 * A bpf_dynptr can't be used as a dynptr if it has been written into at a475 * non-const offset476 */477SEC("?raw_tp")478__failure __msg("cannot overwrite referenced dynptr")479int invalid_write3(void *ctx)480{481	struct bpf_dynptr ptr;482	char stack_buf[16];483	unsigned long len;484	__u8 x = 0;485 486	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);487 488	memcpy(stack_buf, &val, sizeof(val));489	len = stack_buf[0] & 0xf;490 491	memcpy((void *)&ptr + len, &x, sizeof(x));492 493	/* this should fail */494	bpf_ringbuf_submit_dynptr(&ptr, 0);495 496	return 0;497}498 499static int invalid_write4_callback(__u32 index, void *data)500{501	*(__u32 *)data = 123;502 503	return 0;504}505 506/* If the dynptr is written into in a callback function, it should507 * be invalidated as a dynptr508 */509SEC("?raw_tp")510__failure __msg("cannot overwrite referenced dynptr")511int invalid_write4(void *ctx)512{513	struct bpf_dynptr ptr;514 515	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);516 517	bpf_loop(10, invalid_write4_callback, &ptr, 0);518 519	/* this should fail */520	bpf_ringbuf_submit_dynptr(&ptr, 0);521 522	return 0;523}524 525/* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */526struct bpf_dynptr global_dynptr;527 528SEC("?raw_tp")529__failure __msg("type=map_value expected=fp")530int global(void *ctx)531{532	/* this should fail */533	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);534 535	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);536 537	return 0;538}539 540/* A direct read should fail */541SEC("?raw_tp")542__failure __msg("invalid read from stack")543int invalid_read1(void *ctx)544{545	struct bpf_dynptr ptr;546 547	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);548 549	/* this should fail */550	val = *(int *)&ptr;551 552	bpf_ringbuf_discard_dynptr(&ptr, 0);553 554	return 0;555}556 557/* A direct read at an offset should fail */558SEC("?raw_tp")559__failure __msg("cannot pass in dynptr at an offset")560int invalid_read2(void *ctx)561{562	struct bpf_dynptr ptr;563	char read_data[64];564 565	get_map_val_dynptr(&ptr);566 567	/* this should fail */568	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);569 570	return 0;571}572 573/* A direct read at an offset into the lower stack slot should fail */574SEC("?raw_tp")575__failure __msg("invalid read from stack")576int invalid_read3(void *ctx)577{578	struct bpf_dynptr ptr1, ptr2;579 580	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);581	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);582 583	/* this should fail */584	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));585 586	bpf_ringbuf_discard_dynptr(&ptr1, 0);587	bpf_ringbuf_discard_dynptr(&ptr2, 0);588 589	return 0;590}591 592static int invalid_read4_callback(__u32 index, void *data)593{594	/* this should fail */595	val = *(__u32 *)data;596 597	return 0;598}599 600/* A direct read within a callback function should fail */601SEC("?raw_tp")602__failure __msg("invalid read from stack")603int invalid_read4(void *ctx)604{605	struct bpf_dynptr ptr;606 607	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);608 609	bpf_loop(10, invalid_read4_callback, &ptr, 0);610 611	bpf_ringbuf_submit_dynptr(&ptr, 0);612 613	return 0;614}615 616/* Initializing a dynptr on an offset should fail */617SEC("?raw_tp")618__failure __msg("cannot pass in dynptr at an offset=0")619int invalid_offset(void *ctx)620{621	struct bpf_dynptr ptr;622 623	/* this should fail */624	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);625 626	bpf_ringbuf_discard_dynptr(&ptr, 0);627 628	return 0;629}630 631/* Can't release a dynptr twice */632SEC("?raw_tp")633__failure __msg("arg 1 is an unacquired reference")634int release_twice(void *ctx)635{636	struct bpf_dynptr ptr;637 638	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);639 640	bpf_ringbuf_discard_dynptr(&ptr, 0);641 642	/* this second release should fail */643	bpf_ringbuf_discard_dynptr(&ptr, 0);644 645	return 0;646}647 648static int release_twice_callback_fn(__u32 index, void *data)649{650	/* this should fail */651	bpf_ringbuf_discard_dynptr(data, 0);652 653	return 0;654}655 656/* Test that releasing a dynptr twice, where one of the releases happens657 * within a callback function, fails658 */659SEC("?raw_tp")660__failure __msg("arg 1 is an unacquired reference")661int release_twice_callback(void *ctx)662{663	struct bpf_dynptr ptr;664 665	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);666 667	bpf_ringbuf_discard_dynptr(&ptr, 0);668 669	bpf_loop(10, release_twice_callback_fn, &ptr, 0);670 671	return 0;672}673 674/* Reject unsupported local mem types for dynptr_from_mem API */675SEC("?raw_tp")676__failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")677int dynptr_from_mem_invalid_api(void *ctx)678{679	struct bpf_dynptr ptr;680	int x = 0;681 682	/* this should fail */683	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);684 685	return 0;686}687 688SEC("?tc")689__failure __msg("cannot overwrite referenced dynptr") __log_level(2)690int dynptr_pruning_overwrite(struct __sk_buff *ctx)691{692	asm volatile (693		"r9 = 0xeB9F;				\694		 r6 = %[ringbuf] ll;			\695		 r1 = r6;				\696		 r2 = 8;				\697		 r3 = 0;				\698		 r4 = r10;				\699		 r4 += -16;				\700		 call %[bpf_ringbuf_reserve_dynptr];	\701		 if r0 == 0 goto pjmp1;			\702		 goto pjmp2;				\703	pjmp1:						\704		 *(u64 *)(r10 - 16) = r9;		\705	pjmp2:						\706		 r1 = r10;				\707		 r1 += -16;				\708		 r2 = 0;				\709		 call %[bpf_ringbuf_discard_dynptr];	"710		:711		: __imm(bpf_ringbuf_reserve_dynptr),712		  __imm(bpf_ringbuf_discard_dynptr),713		  __imm_addr(ringbuf)714		: __clobber_all715	);716	return 0;717}718 719SEC("?tc")720__success __msg("12: safe") __log_level(2)721int dynptr_pruning_stacksafe(struct __sk_buff *ctx)722{723	asm volatile (724		"r9 = 0xeB9F;				\725		 r6 = %[ringbuf] ll;			\726		 r1 = r6;				\727		 r2 = 8;				\728		 r3 = 0;				\729		 r4 = r10;				\730		 r4 += -16;				\731		 call %[bpf_ringbuf_reserve_dynptr];	\732		 if r0 == 0 goto stjmp1;		\733		 goto stjmp2;				\734	stjmp1:						\735		 r9 = r9;				\736	stjmp2:						\737		 r1 = r10;				\738		 r1 += -16;				\739		 r2 = 0;				\740		 call %[bpf_ringbuf_discard_dynptr];	"741		:742		: __imm(bpf_ringbuf_reserve_dynptr),743		  __imm(bpf_ringbuf_discard_dynptr),744		  __imm_addr(ringbuf)745		: __clobber_all746	);747	return 0;748}749 750SEC("?tc")751__failure __msg("cannot overwrite referenced dynptr") __log_level(2)752int dynptr_pruning_type_confusion(struct __sk_buff *ctx)753{754	asm volatile (755		"r6 = %[array_map4] ll;			\756		 r7 = %[ringbuf] ll;			\757		 r1 = r6;				\758		 r2 = r10;				\759		 r2 += -8;				\760		 r9 = 0;				\761		 *(u64 *)(r2 + 0) = r9;			\762		 r3 = r10;				\763		 r3 += -24;				\764		 r9 = 0xeB9FeB9F;			\765		 *(u64 *)(r10 - 16) = r9;		\766		 *(u64 *)(r10 - 24) = r9;		\767		 r9 = 0;				\768		 r4 = 0;				\769		 r8 = r2;				\770		 call %[bpf_map_update_elem];		\771		 r1 = r6;				\772		 r2 = r8;				\773		 call %[bpf_map_lookup_elem];		\774		 if r0 != 0 goto tjmp1;			\775		 exit;					\776	tjmp1:						\777		 r8 = r0;				\778		 r1 = r7;				\779		 r2 = 8;				\780		 r3 = 0;				\781		 r4 = r10;				\782		 r4 += -16;				\783		 r0 = *(u64 *)(r0 + 0);			\784		 call %[bpf_ringbuf_reserve_dynptr];	\785		 if r0 == 0 goto tjmp2;			\786		 r8 = r8;				\787		 r8 = r8;				\788		 r8 = r8;				\789		 r8 = r8;				\790		 r8 = r8;				\791		 r8 = r8;				\792		 r8 = r8;				\793		 goto tjmp3;				\794	tjmp2:						\795		 *(u64 *)(r10 - 8) = r9;		\796		 *(u64 *)(r10 - 16) = r9;		\797		 r1 = r8;				\798		 r1 += 8;				\799		 r2 = 0;				\800		 r3 = 0;				\801		 r4 = r10;				\802		 r4 += -16;				\803		 call %[bpf_dynptr_from_mem];		\804	tjmp3:						\805		 r1 = r10;				\806		 r1 += -16;				\807		 r2 = 0;				\808		 call %[bpf_ringbuf_discard_dynptr];	"809		:810		: __imm(bpf_map_update_elem),811		  __imm(bpf_map_lookup_elem),812		  __imm(bpf_ringbuf_reserve_dynptr),813		  __imm(bpf_dynptr_from_mem),814		  __imm(bpf_ringbuf_discard_dynptr),815		  __imm_addr(array_map4),816		  __imm_addr(ringbuf)817		: __clobber_all818	);819	return 0;820}821 822SEC("?tc")823__failure __msg("dynptr has to be at a constant offset") __log_level(2)824int dynptr_var_off_overwrite(struct __sk_buff *ctx)825{826	asm volatile (827		"r9 = 16;				\828		 *(u32 *)(r10 - 4) = r9;		\829		 r8 = *(u32 *)(r10 - 4);		\830		 if r8 >= 0 goto vjmp1;			\831		 r0 = 1;				\832		 exit;					\833	vjmp1:						\834		 if r8 <= 16 goto vjmp2;		\835		 r0 = 1;				\836		 exit;					\837	vjmp2:						\838		 r8 &= 16;				\839		 r1 = %[ringbuf] ll;			\840		 r2 = 8;				\841		 r3 = 0;				\842		 r4 = r10;				\843		 r4 += -32;				\844		 r4 += r8;				\845		 call %[bpf_ringbuf_reserve_dynptr];	\846		 r9 = 0xeB9F;				\847		 *(u64 *)(r10 - 16) = r9;		\848		 r1 = r10;				\849		 r1 += -32;				\850		 r1 += r8;				\851		 r2 = 0;				\852		 call %[bpf_ringbuf_discard_dynptr];	"853		:854		: __imm(bpf_ringbuf_reserve_dynptr),855		  __imm(bpf_ringbuf_discard_dynptr),856		  __imm_addr(ringbuf)857		: __clobber_all858	);859	return 0;860}861 862SEC("?tc")863__failure __msg("cannot overwrite referenced dynptr") __log_level(2)864int dynptr_partial_slot_invalidate(struct __sk_buff *ctx)865{866	asm volatile (867		"r6 = %[ringbuf] ll;			\868		 r7 = %[array_map4] ll;			\869		 r1 = r7;				\870		 r2 = r10;				\871		 r2 += -8;				\872		 r9 = 0;				\873		 *(u64 *)(r2 + 0) = r9;			\874		 r3 = r2;				\875		 r4 = 0;				\876		 r8 = r2;				\877		 call %[bpf_map_update_elem];		\878		 r1 = r7;				\879		 r2 = r8;				\880		 call %[bpf_map_lookup_elem];		\881		 if r0 != 0 goto sjmp1;			\882		 exit;					\883	sjmp1:						\884		 r7 = r0;				\885		 r1 = r6;				\886		 r2 = 8;				\887		 r3 = 0;				\888		 r4 = r10;				\889		 r4 += -24;				\890		 call %[bpf_ringbuf_reserve_dynptr];	\891		 *(u64 *)(r10 - 16) = r9;		\892		 r1 = r7;				\893		 r2 = 8;				\894		 r3 = 0;				\895		 r4 = r10;				\896		 r4 += -16;				\897		 call %[bpf_dynptr_from_mem];		\898		 r1 = r10;				\899		 r1 += -512;				\900		 r2 = 488;				\901		 r3 = r10;				\902		 r3 += -24;				\903		 r4 = 0;				\904		 r5 = 0;				\905		 call %[bpf_dynptr_read];		\906		 r8 = 1;				\907		 if r0 != 0 goto sjmp2;			\908		 r8 = 0;				\909	sjmp2:						\910		 r1 = r10;				\911		 r1 += -24;				\912		 r2 = 0;				\913		 call %[bpf_ringbuf_discard_dynptr];	"914		:915		: __imm(bpf_map_update_elem),916		  __imm(bpf_map_lookup_elem),917		  __imm(bpf_ringbuf_reserve_dynptr),918		  __imm(bpf_ringbuf_discard_dynptr),919		  __imm(bpf_dynptr_from_mem),920		  __imm(bpf_dynptr_read),921		  __imm_addr(ringbuf),922		  __imm_addr(array_map4)923		: __clobber_all924	);925	return 0;926}927 928/* Test that it is allowed to overwrite unreferenced dynptr. */929SEC("?raw_tp")930__success931int dynptr_overwrite_unref(void *ctx)932{933	struct bpf_dynptr ptr;934 935	if (get_map_val_dynptr(&ptr))936		return 0;937	if (get_map_val_dynptr(&ptr))938		return 0;939	if (get_map_val_dynptr(&ptr))940		return 0;941 942	return 0;943}944 945/* Test that slices are invalidated on reinitializing a dynptr. */946SEC("?raw_tp")947__failure __msg("invalid mem access 'scalar'")948int dynptr_invalidate_slice_reinit(void *ctx)949{950	struct bpf_dynptr ptr;951	__u8 *p;952 953	if (get_map_val_dynptr(&ptr))954		return 0;955	p = bpf_dynptr_data(&ptr, 0, 1);956	if (!p)957		return 0;958	if (get_map_val_dynptr(&ptr))959		return 0;960	/* this should fail */961	return *p;962}963 964/* Invalidation of dynptr slices on destruction of dynptr should not miss965 * mem_or_null pointers.966 */967SEC("?raw_tp")968__failure __msg("R{{[0-9]+}} type=scalar expected=percpu_ptr_")969int dynptr_invalidate_slice_or_null(void *ctx)970{971	struct bpf_dynptr ptr;972	__u8 *p;973 974	if (get_map_val_dynptr(&ptr))975		return 0;976 977	p = bpf_dynptr_data(&ptr, 0, 1);978	*(__u8 *)&ptr = 0;979	/* this should fail */980	bpf_this_cpu_ptr(p);981	return 0;982}983 984/* Destruction of dynptr should also any slices obtained from it */985SEC("?raw_tp")986__failure __msg("R{{[0-9]+}} invalid mem access 'scalar'")987int dynptr_invalidate_slice_failure(void *ctx)988{989	struct bpf_dynptr ptr1;990	struct bpf_dynptr ptr2;991	__u8 *p1, *p2;992 993	if (get_map_val_dynptr(&ptr1))994		return 0;995	if (get_map_val_dynptr(&ptr2))996		return 0;997 998	p1 = bpf_dynptr_data(&ptr1, 0, 1);999	if (!p1)1000		return 0;1001	p2 = bpf_dynptr_data(&ptr2, 0, 1);1002	if (!p2)1003		return 0;1004 1005	*(__u8 *)&ptr1 = 0;1006	/* this should fail */1007	return *p1;1008}1009 1010/* Invalidation of slices should be scoped and should not prevent dereferencing1011 * slices of another dynptr after destroying unrelated dynptr1012 */1013SEC("?raw_tp")1014__success1015int dynptr_invalidate_slice_success(void *ctx)1016{1017	struct bpf_dynptr ptr1;1018	struct bpf_dynptr ptr2;1019	__u8 *p1, *p2;1020 1021	if (get_map_val_dynptr(&ptr1))1022		return 1;1023	if (get_map_val_dynptr(&ptr2))1024		return 1;1025 1026	p1 = bpf_dynptr_data(&ptr1, 0, 1);1027	if (!p1)1028		return 1;1029	p2 = bpf_dynptr_data(&ptr2, 0, 1);1030	if (!p2)1031		return 1;1032 1033	*(__u8 *)&ptr1 = 0;1034	return *p2;1035}1036 1037/* Overwriting referenced dynptr should be rejected */1038SEC("?raw_tp")1039__failure __msg("cannot overwrite referenced dynptr")1040int dynptr_overwrite_ref(void *ctx)1041{1042	struct bpf_dynptr ptr;1043 1044	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);1045	/* this should fail */1046	if (get_map_val_dynptr(&ptr))1047		bpf_ringbuf_discard_dynptr(&ptr, 0);1048	return 0;1049}1050 1051/* Reject writes to dynptr slot from bpf_dynptr_read */1052SEC("?raw_tp")1053__failure __msg("potential write to dynptr at off=-16")1054int dynptr_read_into_slot(void *ctx)1055{1056	union {1057		struct {1058			char _pad[48];1059			struct bpf_dynptr ptr;1060		};1061		char buf[64];1062	} data;1063 1064	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr);1065	/* this should fail */1066	bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0);1067 1068	return 0;1069}1070 1071/* bpf_dynptr_slice()s are read-only and cannot be written to */1072SEC("?tc")1073__failure __msg("R{{[0-9]+}} cannot write into rdonly_mem")1074int skb_invalid_slice_write(struct __sk_buff *skb)1075{1076	struct bpf_dynptr ptr;1077	struct ethhdr *hdr;1078	char buffer[sizeof(*hdr)] = {};1079 1080	bpf_dynptr_from_skb(skb, 0, &ptr);1081 1082	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));1083	if (!hdr)1084		return SK_DROP;1085 1086	/* this should fail */1087	hdr->h_proto = 1;1088 1089	return SK_PASS;1090}1091 1092/* The read-only data slice is invalidated whenever a helper changes packet data */1093SEC("?tc")1094__failure __msg("invalid mem access 'scalar'")1095int skb_invalid_data_slice1(struct __sk_buff *skb)1096{1097	struct bpf_dynptr ptr;1098	struct ethhdr *hdr;1099	char buffer[sizeof(*hdr)] = {};1100 1101	bpf_dynptr_from_skb(skb, 0, &ptr);1102 1103	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));1104	if (!hdr)1105		return SK_DROP;1106 1107	val = hdr->h_proto;1108 1109	if (bpf_skb_pull_data(skb, skb->len))1110		return SK_DROP;1111 1112	/* this should fail */1113	val = hdr->h_proto;1114 1115	return SK_PASS;1116}1117 1118/* The read-write data slice is invalidated whenever a helper changes packet data */1119SEC("?tc")1120__failure __msg("invalid mem access 'scalar'")1121int skb_invalid_data_slice2(struct __sk_buff *skb)1122{1123	struct bpf_dynptr ptr;1124	struct ethhdr *hdr;1125	char buffer[sizeof(*hdr)] = {};1126 1127	bpf_dynptr_from_skb(skb, 0, &ptr);1128 1129	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));1130	if (!hdr)1131		return SK_DROP;1132 1133	hdr->h_proto = 123;1134 1135	if (bpf_skb_pull_data(skb, skb->len))1136		return SK_DROP;1137 1138	/* this should fail */1139	hdr->h_proto = 1;1140 1141	return SK_PASS;1142}1143 1144/* The read-only data slice is invalidated whenever bpf_dynptr_write() is called */1145SEC("?tc")1146__failure __msg("invalid mem access 'scalar'")1147int skb_invalid_data_slice3(struct __sk_buff *skb)1148{1149	char write_data[64] = "hello there, world!!";1150	struct bpf_dynptr ptr;1151	struct ethhdr *hdr;1152	char buffer[sizeof(*hdr)] = {};1153 1154	bpf_dynptr_from_skb(skb, 0, &ptr);1155 1156	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));1157	if (!hdr)1158		return SK_DROP;1159 1160	val = hdr->h_proto;1161 1162	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);1163 1164	/* this should fail */1165	val = hdr->h_proto;1166 1167	return SK_PASS;1168}1169 1170/* The read-write data slice is invalidated whenever bpf_dynptr_write() is called */1171SEC("?tc")1172__failure __msg("invalid mem access 'scalar'")1173int skb_invalid_data_slice4(struct __sk_buff *skb)1174{1175	char write_data[64] = "hello there, world!!";1176	struct bpf_dynptr ptr;1177	struct ethhdr *hdr;1178	char buffer[sizeof(*hdr)] = {};1179 1180	bpf_dynptr_from_skb(skb, 0, &ptr);1181	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));1182	if (!hdr)1183		return SK_DROP;1184 1185	hdr->h_proto = 123;1186 1187	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);1188 1189	/* this should fail */1190	hdr->h_proto = 1;1191 1192	return SK_PASS;1193}1194 1195/* The read-only data slice is invalidated whenever a helper changes packet data */1196SEC("?xdp")1197__failure __msg("invalid mem access 'scalar'")1198int xdp_invalid_data_slice1(struct xdp_md *xdp)1199{1200	struct bpf_dynptr ptr;1201	struct ethhdr *hdr;1202	char buffer[sizeof(*hdr)] = {};1203 1204	bpf_dynptr_from_xdp(xdp, 0, &ptr);1205	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));1206	if (!hdr)1207		return SK_DROP;1208 1209	val = hdr->h_proto;1210 1211	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))1212		return XDP_DROP;1213 1214	/* this should fail */1215	val = hdr->h_proto;1216 1217	return XDP_PASS;1218}1219 1220/* The read-write data slice is invalidated whenever a helper changes packet data */1221SEC("?xdp")1222__failure __msg("invalid mem access 'scalar'")1223int xdp_invalid_data_slice2(struct xdp_md *xdp)1224{1225	struct bpf_dynptr ptr;1226	struct ethhdr *hdr;1227	char buffer[sizeof(*hdr)] = {};1228 1229	bpf_dynptr_from_xdp(xdp, 0, &ptr);1230	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));1231	if (!hdr)1232		return SK_DROP;1233 1234	hdr->h_proto = 9;1235 1236	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))1237		return XDP_DROP;1238 1239	/* this should fail */1240	hdr->h_proto = 1;1241 1242	return XDP_PASS;1243}1244 1245/* Only supported prog type can create skb-type dynptrs */1246SEC("?raw_tp")1247__failure __msg("calling kernel function bpf_dynptr_from_skb is not allowed")1248int skb_invalid_ctx(void *ctx)1249{1250	struct bpf_dynptr ptr;1251 1252	/* this should fail */1253	bpf_dynptr_from_skb(ctx, 0, &ptr);1254 1255	return 0;1256}1257 1258SEC("fentry/skb_tx_error")1259__failure __msg("must be referenced or trusted")1260int BPF_PROG(skb_invalid_ctx_fentry, void *skb)1261{1262	struct bpf_dynptr ptr;1263 1264	/* this should fail */1265	bpf_dynptr_from_skb(skb, 0, &ptr);1266 1267	return 0;1268}1269 1270SEC("fexit/skb_tx_error")1271__failure __msg("must be referenced or trusted")1272int BPF_PROG(skb_invalid_ctx_fexit, void *skb)1273{1274	struct bpf_dynptr ptr;1275 1276	/* this should fail */1277	bpf_dynptr_from_skb(skb, 0, &ptr);1278 1279	return 0;1280}1281 1282/* Reject writes to dynptr slot for uninit arg */1283SEC("?raw_tp")1284__failure __msg("potential write to dynptr at off=-16")1285int uninit_write_into_slot(void *ctx)1286{1287	struct {1288		char buf[64];1289		struct bpf_dynptr ptr;1290	} data;1291 1292	bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr);1293	/* this should fail */1294	bpf_get_current_comm(data.buf, 80);1295 1296	return 0;1297}1298 1299/* Only supported prog type can create xdp-type dynptrs */1300SEC("?raw_tp")1301__failure __msg("calling kernel function bpf_dynptr_from_xdp is not allowed")1302int xdp_invalid_ctx(void *ctx)1303{1304	struct bpf_dynptr ptr;1305 1306	/* this should fail */1307	bpf_dynptr_from_xdp(ctx, 0, &ptr);1308 1309	return 0;1310}1311 1312__u32 hdr_size = sizeof(struct ethhdr);1313/* Can't pass in variable-sized len to bpf_dynptr_slice */1314SEC("?tc")1315__failure __msg("unbounded memory access")1316int dynptr_slice_var_len1(struct __sk_buff *skb)1317{1318	struct bpf_dynptr ptr;1319	struct ethhdr *hdr;1320	char buffer[sizeof(*hdr)] = {};1321 1322	bpf_dynptr_from_skb(skb, 0, &ptr);1323 1324	/* this should fail */1325	hdr = bpf_dynptr_slice(&ptr, 0, buffer, hdr_size);1326	if (!hdr)1327		return SK_DROP;1328 1329	return SK_PASS;1330}1331 1332/* Can't pass in variable-sized len to bpf_dynptr_slice */1333SEC("?tc")1334__failure __msg("must be a known constant")1335int dynptr_slice_var_len2(struct __sk_buff *skb)1336{1337	char buffer[sizeof(struct ethhdr)] = {};1338	struct bpf_dynptr ptr;1339	struct ethhdr *hdr;1340 1341	bpf_dynptr_from_skb(skb, 0, &ptr);1342 1343	if (hdr_size <= sizeof(buffer)) {1344		/* this should fail */1345		hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, hdr_size);1346		if (!hdr)1347			return SK_DROP;1348		hdr->h_proto = 12;1349	}1350 1351	return SK_PASS;1352}1353 1354static int callback(__u32 index, void *data)1355{1356        *(__u32 *)data = 123;1357 1358        return 0;1359}1360 1361/* If the dynptr is written into in a callback function, its data1362 * slices should be invalidated as well.1363 */1364SEC("?raw_tp")1365__failure __msg("invalid mem access 'scalar'")1366int invalid_data_slices(void *ctx)1367{1368	struct bpf_dynptr ptr;1369	__u32 *slice;1370 1371	if (get_map_val_dynptr(&ptr))1372		return 0;1373 1374	slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));1375	if (!slice)1376		return 0;1377 1378	bpf_loop(10, callback, &ptr, 0);1379 1380	/* this should fail */1381	*slice = 1;1382 1383	return 0;1384}1385 1386/* Program types that don't allow writes to packet data should fail if1387 * bpf_dynptr_slice_rdwr is called1388 */1389SEC("cgroup_skb/ingress")1390__failure __msg("the prog does not allow writes to packet data")1391int invalid_slice_rdwr_rdonly(struct __sk_buff *skb)1392{1393	char buffer[sizeof(struct ethhdr)] = {};1394	struct bpf_dynptr ptr;1395	struct ethhdr *hdr;1396 1397	bpf_dynptr_from_skb(skb, 0, &ptr);1398 1399	/* this should fail since cgroup_skb doesn't allow1400	 * changing packet data1401	 */1402	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));1403	__sink(hdr);1404 1405	return 0;1406}1407 1408/* bpf_dynptr_adjust can only be called on initialized dynptrs */1409SEC("?raw_tp")1410__failure __msg("Expected an initialized dynptr as arg #1")1411int dynptr_adjust_invalid(void *ctx)1412{1413	struct bpf_dynptr ptr = {};1414 1415	/* this should fail */1416	bpf_dynptr_adjust(&ptr, 1, 2);1417 1418	return 0;1419}1420 1421/* bpf_dynptr_is_null can only be called on initialized dynptrs */1422SEC("?raw_tp")1423__failure __msg("Expected an initialized dynptr as arg #1")1424int dynptr_is_null_invalid(void *ctx)1425{1426	struct bpf_dynptr ptr = {};1427 1428	/* this should fail */1429	bpf_dynptr_is_null(&ptr);1430 1431	return 0;1432}1433 1434/* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */1435SEC("?raw_tp")1436__failure __msg("Expected an initialized dynptr as arg #1")1437int dynptr_is_rdonly_invalid(void *ctx)1438{1439	struct bpf_dynptr ptr = {};1440 1441	/* this should fail */1442	bpf_dynptr_is_rdonly(&ptr);1443 1444	return 0;1445}1446 1447/* bpf_dynptr_size can only be called on initialized dynptrs */1448SEC("?raw_tp")1449__failure __msg("Expected an initialized dynptr as arg #1")1450int dynptr_size_invalid(void *ctx)1451{1452	struct bpf_dynptr ptr = {};1453 1454	/* this should fail */1455	bpf_dynptr_size(&ptr);1456 1457	return 0;1458}1459 1460/* Only initialized dynptrs can be cloned */1461SEC("?raw_tp")1462__failure __msg("Expected an initialized dynptr as arg #1")1463int clone_invalid1(void *ctx)1464{1465	struct bpf_dynptr ptr1 = {};1466	struct bpf_dynptr ptr2;1467 1468	/* this should fail */1469	bpf_dynptr_clone(&ptr1, &ptr2);1470 1471	return 0;1472}1473 1474/* Can't overwrite an existing dynptr when cloning */1475SEC("?xdp")1476__failure __msg("cannot overwrite referenced dynptr")1477int clone_invalid2(struct xdp_md *xdp)1478{1479	struct bpf_dynptr ptr1;1480	struct bpf_dynptr clone;1481 1482	bpf_dynptr_from_xdp(xdp, 0, &ptr1);1483 1484	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &clone);1485 1486	/* this should fail */1487	bpf_dynptr_clone(&ptr1, &clone);1488 1489	bpf_ringbuf_submit_dynptr(&clone, 0);1490 1491	return 0;1492}1493 1494/* Invalidating a dynptr should invalidate its clones */1495SEC("?raw_tp")1496__failure __msg("Expected an initialized dynptr as arg #3")1497int clone_invalidate1(void *ctx)1498{1499	struct bpf_dynptr clone;1500	struct bpf_dynptr ptr;1501	char read_data[64];1502 1503	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1504 1505	bpf_dynptr_clone(&ptr, &clone);1506 1507	bpf_ringbuf_submit_dynptr(&ptr, 0);1508 1509	/* this should fail */1510	bpf_dynptr_read(read_data, sizeof(read_data), &clone, 0, 0);1511 1512	return 0;1513}1514 1515/* Invalidating a dynptr should invalidate its parent */1516SEC("?raw_tp")1517__failure __msg("Expected an initialized dynptr as arg #3")1518int clone_invalidate2(void *ctx)1519{1520	struct bpf_dynptr ptr;1521	struct bpf_dynptr clone;1522	char read_data[64];1523 1524	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1525 1526	bpf_dynptr_clone(&ptr, &clone);1527 1528	bpf_ringbuf_submit_dynptr(&clone, 0);1529 1530	/* this should fail */1531	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);1532 1533	return 0;1534}1535 1536/* Invalidating a dynptr should invalidate its siblings */1537SEC("?raw_tp")1538__failure __msg("Expected an initialized dynptr as arg #3")1539int clone_invalidate3(void *ctx)1540{1541	struct bpf_dynptr ptr;1542	struct bpf_dynptr clone1;1543	struct bpf_dynptr clone2;1544	char read_data[64];1545 1546	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1547 1548	bpf_dynptr_clone(&ptr, &clone1);1549 1550	bpf_dynptr_clone(&ptr, &clone2);1551 1552	bpf_ringbuf_submit_dynptr(&clone2, 0);1553 1554	/* this should fail */1555	bpf_dynptr_read(read_data, sizeof(read_data), &clone1, 0, 0);1556 1557	return 0;1558}1559 1560/* Invalidating a dynptr should invalidate any data slices1561 * of its clones1562 */1563SEC("?raw_tp")1564__failure __msg("invalid mem access 'scalar'")1565int clone_invalidate4(void *ctx)1566{1567	struct bpf_dynptr ptr;1568	struct bpf_dynptr clone;1569	int *data;1570 1571	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1572 1573	bpf_dynptr_clone(&ptr, &clone);1574	data = bpf_dynptr_data(&clone, 0, sizeof(val));1575	if (!data)1576		return 0;1577 1578	bpf_ringbuf_submit_dynptr(&ptr, 0);1579 1580	/* this should fail */1581	*data = 123;1582 1583	return 0;1584}1585 1586/* Invalidating a dynptr should invalidate any data slices1587 * of its parent1588 */1589SEC("?raw_tp")1590__failure __msg("invalid mem access 'scalar'")1591int clone_invalidate5(void *ctx)1592{1593	struct bpf_dynptr ptr;1594	struct bpf_dynptr clone;1595	int *data;1596 1597	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1598	data = bpf_dynptr_data(&ptr, 0, sizeof(val));1599	if (!data)1600		return 0;1601 1602	bpf_dynptr_clone(&ptr, &clone);1603 1604	bpf_ringbuf_submit_dynptr(&clone, 0);1605 1606	/* this should fail */1607	*data = 123;1608 1609	return 0;1610}1611 1612/* Invalidating a dynptr should invalidate any data slices1613 * of its sibling1614 */1615SEC("?raw_tp")1616__failure __msg("invalid mem access 'scalar'")1617int clone_invalidate6(void *ctx)1618{1619	struct bpf_dynptr ptr;1620	struct bpf_dynptr clone1;1621	struct bpf_dynptr clone2;1622	int *data;1623 1624	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);1625 1626	bpf_dynptr_clone(&ptr, &clone1);1627 1628	bpf_dynptr_clone(&ptr, &clone2);1629 1630	data = bpf_dynptr_data(&clone1, 0, sizeof(val));1631	if (!data)1632		return 0;1633 1634	bpf_ringbuf_submit_dynptr(&clone2, 0);1635 1636	/* this should fail */1637	*data = 123;1638 1639	return 0;1640}1641 1642/* A skb clone's data slices should be invalid anytime packet data changes */1643SEC("?tc")1644__failure __msg("invalid mem access 'scalar'")1645int clone_skb_packet_data(struct __sk_buff *skb)1646{1647	char buffer[sizeof(__u32)] = {};1648	struct bpf_dynptr clone;1649	struct bpf_dynptr ptr;1650	__u32 *data;1651 1652	bpf_dynptr_from_skb(skb, 0, &ptr);1653 1654	bpf_dynptr_clone(&ptr, &clone);1655	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));1656	if (!data)1657		return XDP_DROP;1658 1659	if (bpf_skb_pull_data(skb, skb->len))1660		return SK_DROP;1661 1662	/* this should fail */1663	*data = 123;1664 1665	return 0;1666}1667 1668/* A xdp clone's data slices should be invalid anytime packet data changes */1669SEC("?xdp")1670__failure __msg("invalid mem access 'scalar'")1671int clone_xdp_packet_data(struct xdp_md *xdp)1672{1673	char buffer[sizeof(__u32)] = {};1674	struct bpf_dynptr clone;1675	struct bpf_dynptr ptr;1676	struct ethhdr *hdr;1677	__u32 *data;1678 1679	bpf_dynptr_from_xdp(xdp, 0, &ptr);1680 1681	bpf_dynptr_clone(&ptr, &clone);1682	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));1683	if (!data)1684		return XDP_DROP;1685 1686	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))1687		return XDP_DROP;1688 1689	/* this should fail */1690	*data = 123;1691 1692	return 0;1693}1694 1695/* Buffers that are provided must be sufficiently long */1696SEC("?cgroup_skb/egress")1697__failure __msg("memory, len pair leads to invalid memory access")1698int test_dynptr_skb_small_buff(struct __sk_buff *skb)1699{1700	struct bpf_dynptr ptr;1701	char buffer[8] = {};1702	__u64 *data;1703 1704	if (bpf_dynptr_from_skb(skb, 0, &ptr)) {1705		err = 1;1706		return 1;1707	}1708 1709	/* This may return NULL. SKB may require a buffer */1710	data = bpf_dynptr_slice(&ptr, 0, buffer, 9);1711 1712	return !!data;1713}1714 1715__noinline long global_call_bpf_dynptr(const struct bpf_dynptr *dynptr)1716{1717	long ret = 0;1718	/* Avoid leaving this global function empty to avoid having the compiler1719	 * optimize away the call to this global function.1720	 */1721	__sink(ret);1722	return ret;1723}1724 1725SEC("?raw_tp")1726__failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr")1727int test_dynptr_reg_type(void *ctx)1728{1729	struct task_struct *current = NULL;1730	/* R1 should be holding a PTR_TO_BTF_ID, so this shouldn't be a1731	 * reg->type that can be passed to a function accepting a1732	 * ARG_PTR_TO_DYNPTR | MEM_RDONLY. process_dynptr_func() should catch1733	 * this.1734	 */1735	global_call_bpf_dynptr((const struct bpf_dynptr *)current);1736	return 0;1737}1738