Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   1// SPDX-License-Identifier: GPL-2.0
   2/* 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 corresponding
  78 * bpf_ringbuf_submit/discard_dynptr call
  79 */
  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 #2")
 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 a
 398 * dynptr argument
 399 */
 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 #0")
 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 fixed
 451 * offset
 452 */
 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 a
 475 * non-const offset
 476 */
 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 should
 507 * be invalidated as a dynptr
 508 */
 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 happens
 657 * within a callback function, fails
 658 */
 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_all
 715	);
 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_all
 746	);
 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_all
 818	);
 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_all
 858	);
 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_all
 924	);
 925	return 0;
 926}
 927
 928/* Test that it is allowed to overwrite unreferenced dynptr. */
 929SEC("?raw_tp")
 930__success
 931int 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 miss
 965 * 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 dereferencing
1011 * slices of another dynptr after destroying unrelated dynptr
1012 */
1013SEC("?raw_tp")
1014__success
1015int 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 data
1362 * 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 if
1387 * bpf_dynptr_slice_rdwr is called
1388 */
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 allow
1400	 * changing packet data
1401	 */
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 #0")
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 #0")
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 #0")
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 #0")
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 #0")
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 #2")
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 #2")
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 #2")
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 slices
1561 * of its clones
1562 */
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 slices
1587 * of its parent
1588 */
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 slices
1613 * of its sibling
1614 */
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 compiler
1719	 * optimize away the call to this global function.
1720	 */
1721	__sink(ret);
1722	return ret;
1723}
1724
1725SEC("?raw_tp")
1726__failure __msg("arg#0 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 a
1731	 * reg->type that can be passed to a function accepting a
1732	 * ARG_PTR_TO_DYNPTR | MEM_RDONLY. process_dynptr_func() should catch
1733	 * this.
1734	 */
1735	global_call_bpf_dynptr((const struct bpf_dynptr *)current);
1736	return 0;
1737}