Linux Audio

Check our new training course

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