Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.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}