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} 1689