1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Facebook */ 3 4 #include <errno.h> 5 #include <string.h> 6 #include <linux/bpf.h> 7 #include <bpf/bpf_helpers.h> 8 #include "bpf_misc.h" 9 10 char _license[] SEC("license") = "GPL"; 11 12 struct test_info { 13 int x; 14 struct bpf_dynptr ptr; 15 }; 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_ARRAY); 19 __uint(max_entries, 1); 20 __type(key, __u32); 21 __type(value, struct bpf_dynptr); 22 } array_map1 SEC(".maps"); 23 24 struct { 25 __uint(type, BPF_MAP_TYPE_ARRAY); 26 __uint(max_entries, 1); 27 __type(key, __u32); 28 __type(value, struct test_info); 29 } array_map2 SEC(".maps"); 30 31 struct { 32 __uint(type, BPF_MAP_TYPE_ARRAY); 33 __uint(max_entries, 1); 34 __type(key, __u32); 35 __type(value, __u32); 36 } array_map3 SEC(".maps"); 37 38 struct { 39 __uint(type, BPF_MAP_TYPE_ARRAY); 40 __uint(max_entries, 1); 41 __type(key, __u32); 42 __type(value, __u64); 43 } array_map4 SEC(".maps"); 44 45 struct sample { 46 int pid; 47 long value; 48 char comm[16]; 49 }; 50 51 struct { 52 __uint(type, BPF_MAP_TYPE_RINGBUF); 53 __uint(max_entries, 4096); 54 } ringbuf SEC(".maps"); 55 56 int err, val; 57 58 static int get_map_val_dynptr(struct bpf_dynptr *ptr) 59 { 60 __u32 key = 0, *map_val; 61 62 bpf_map_update_elem(&array_map3, &key, &val, 0); 63 64 map_val = bpf_map_lookup_elem(&array_map3, &key); 65 if (!map_val) 66 return -ENOENT; 67 68 bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr); 69 70 return 0; 71 } 72 73 /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding 74 * bpf_ringbuf_submit/discard_dynptr call 75 */ 76 SEC("?raw_tp") 77 __failure __msg("Unreleased reference id=2") 78 int ringbuf_missing_release1(void *ctx) 79 { 80 struct bpf_dynptr ptr; 81 82 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr); 83 84 /* missing a call to bpf_ringbuf_discard/submit_dynptr */ 85 86 return 0; 87 } 88 89 SEC("?raw_tp") 90 __failure __msg("Unreleased reference id=4") 91 int ringbuf_missing_release2(void *ctx) 92 { 93 struct bpf_dynptr ptr1, ptr2; 94 struct sample *sample; 95 96 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1); 97 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2); 98 99 sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample)); 100 if (!sample) { 101 bpf_ringbuf_discard_dynptr(&ptr1, 0); 102 bpf_ringbuf_discard_dynptr(&ptr2, 0); 103 return 0; 104 } 105 106 bpf_ringbuf_submit_dynptr(&ptr1, 0); 107 108 /* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */ 109 110 return 0; 111 } 112 113 static int missing_release_callback_fn(__u32 index, void *data) 114 { 115 struct bpf_dynptr ptr; 116 117 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr); 118 119 /* missing a call to bpf_ringbuf_discard/submit_dynptr */ 120 121 return 0; 122 } 123 124 /* Any dynptr initialized within a callback must have bpf_dynptr_put called */ 125 SEC("?raw_tp") 126 __failure __msg("Unreleased reference id") 127 int ringbuf_missing_release_callback(void *ctx) 128 { 129 bpf_loop(10, missing_release_callback_fn, NULL, 0); 130 return 0; 131 } 132 133 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */ 134 SEC("?raw_tp") 135 __failure __msg("arg 1 is an unacquired reference") 136 int ringbuf_release_uninit_dynptr(void *ctx) 137 { 138 struct bpf_dynptr ptr; 139 140 /* this should fail */ 141 bpf_ringbuf_submit_dynptr(&ptr, 0); 142 143 return 0; 144 } 145 146 /* A dynptr can't be used after it has been invalidated */ 147 SEC("?raw_tp") 148 __failure __msg("Expected an initialized dynptr as arg #3") 149 int use_after_invalid(void *ctx) 150 { 151 struct bpf_dynptr ptr; 152 char read_data[64]; 153 154 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr); 155 156 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); 157 158 bpf_ringbuf_submit_dynptr(&ptr, 0); 159 160 /* this should fail */ 161 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); 162 163 return 0; 164 } 165 166 /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */ 167 SEC("?raw_tp") 168 __failure __msg("type=mem expected=ringbuf_mem") 169 int ringbuf_invalid_api(void *ctx) 170 { 171 struct bpf_dynptr ptr; 172 struct sample *sample; 173 174 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr); 175 sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample)); 176 if (!sample) 177 goto done; 178 179 sample->pid = 123; 180 181 /* invalid API use. need to use dynptr API to submit/discard */ 182 bpf_ringbuf_submit(sample, 0); 183 184 done: 185 bpf_ringbuf_discard_dynptr(&ptr, 0); 186 return 0; 187 } 188 189 /* Can't add a dynptr to a map */ 190 SEC("?raw_tp") 191 __failure __msg("invalid indirect read from stack") 192 int add_dynptr_to_map1(void *ctx) 193 { 194 struct bpf_dynptr ptr; 195 int key = 0; 196 197 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr); 198 199 /* this should fail */ 200 bpf_map_update_elem(&array_map1, &key, &ptr, 0); 201 202 bpf_ringbuf_submit_dynptr(&ptr, 0); 203 204 return 0; 205 } 206 207 /* Can't add a struct with an embedded dynptr to a map */ 208 SEC("?raw_tp") 209 __failure __msg("invalid indirect read from stack") 210 int add_dynptr_to_map2(void *ctx) 211 { 212 struct test_info x; 213 int key = 0; 214 215 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr); 216 217 /* this should fail */ 218 bpf_map_update_elem(&array_map2, &key, &x, 0); 219 220 bpf_ringbuf_submit_dynptr(&x.ptr, 0); 221 222 return 0; 223 } 224 225 /* A data slice can't be accessed out of bounds */ 226 SEC("?raw_tp") 227 __failure __msg("value is outside of the allowed memory range") 228 int data_slice_out_of_bounds_ringbuf(void *ctx) 229 { 230 struct bpf_dynptr ptr; 231 void *data; 232 233 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr); 234 235 data = bpf_dynptr_data(&ptr, 0, 8); 236 if (!data) 237 goto done; 238 239 /* can't index out of bounds of the data slice */ 240 val = *((char *)data + 8); 241 242 done: 243 bpf_ringbuf_submit_dynptr(&ptr, 0); 244 return 0; 245 } 246 247 SEC("?raw_tp") 248 __failure __msg("value is outside of the allowed memory range") 249 int data_slice_out_of_bounds_map_value(void *ctx) 250 { 251 __u32 key = 0, map_val; 252 struct bpf_dynptr ptr; 253 void *data; 254 255 get_map_val_dynptr(&ptr); 256 257 data = bpf_dynptr_data(&ptr, 0, sizeof(map_val)); 258 if (!data) 259 return 0; 260 261 /* can't index out of bounds of the data slice */ 262 val = *((char *)data + (sizeof(map_val) + 1)); 263 264 return 0; 265 } 266 267 /* A data slice can't be used after it has been released */ 268 SEC("?raw_tp") 269 __failure __msg("invalid mem access 'scalar'") 270 int data_slice_use_after_release1(void *ctx) 271 { 272 struct bpf_dynptr ptr; 273 struct sample *sample; 274 275 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr); 276 sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample)); 277 if (!sample) 278 goto done; 279 280 sample->pid = 123; 281 282 bpf_ringbuf_submit_dynptr(&ptr, 0); 283 284 /* this should fail */ 285 val = sample->pid; 286 287 return 0; 288 289 done: 290 bpf_ringbuf_discard_dynptr(&ptr, 0); 291 return 0; 292 } 293 294 /* A data slice can't be used after it has been released. 295 * 296 * This tests the case where the data slice tracks a dynptr (ptr2) 297 * that is at a non-zero offset from the frame pointer (ptr1 is at fp, 298 * ptr2 is at fp - 16). 299 */ 300 SEC("?raw_tp") 301 __failure __msg("invalid mem access 'scalar'") 302 int data_slice_use_after_release2(void *ctx) 303 { 304 struct bpf_dynptr ptr1, ptr2; 305 struct sample *sample; 306 307 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1); 308 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2); 309 310 sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample)); 311 if (!sample) 312 goto done; 313 314 sample->pid = 23; 315 316 bpf_ringbuf_submit_dynptr(&ptr2, 0); 317 318 /* this should fail */ 319 sample->pid = 23; 320 321 bpf_ringbuf_submit_dynptr(&ptr1, 0); 322 323 return 0; 324 325 done: 326 bpf_ringbuf_discard_dynptr(&ptr2, 0); 327 bpf_ringbuf_discard_dynptr(&ptr1, 0); 328 return 0; 329 } 330 331 /* A data slice must be first checked for NULL */ 332 SEC("?raw_tp") 333 __failure __msg("invalid mem access 'mem_or_null'") 334 int data_slice_missing_null_check1(void *ctx) 335 { 336 struct bpf_dynptr ptr; 337 void *data; 338 339 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr); 340 341 data = bpf_dynptr_data(&ptr, 0, 8); 342 343 /* missing if (!data) check */ 344 345 /* this should fail */ 346 *(__u8 *)data = 3; 347 348 bpf_ringbuf_submit_dynptr(&ptr, 0); 349 return 0; 350 } 351 352 /* A data slice can't be dereferenced if it wasn't checked for null */ 353 SEC("?raw_tp") 354 __failure __msg("invalid mem access 'mem_or_null'") 355 int data_slice_missing_null_check2(void *ctx) 356 { 357 struct bpf_dynptr ptr; 358 __u64 *data1, *data2; 359 360 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr); 361 362 data1 = bpf_dynptr_data(&ptr, 0, 8); 363 data2 = bpf_dynptr_data(&ptr, 0, 8); 364 if (data1) 365 /* this should fail */ 366 *data2 = 3; 367 368 done: 369 bpf_ringbuf_discard_dynptr(&ptr, 0); 370 return 0; 371 } 372 373 /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a 374 * dynptr argument 375 */ 376 SEC("?raw_tp") 377 __failure __msg("invalid indirect read from stack") 378 int invalid_helper1(void *ctx) 379 { 380 struct bpf_dynptr ptr; 381 382 get_map_val_dynptr(&ptr); 383 384 /* this should fail */ 385 bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!"); 386 387 return 0; 388 } 389 390 /* A dynptr can't be passed into a helper function at a non-zero offset */ 391 SEC("?raw_tp") 392 __failure __msg("cannot pass in dynptr at an offset=-8") 393 int invalid_helper2(void *ctx) 394 { 395 struct bpf_dynptr ptr; 396 char read_data[64]; 397 398 get_map_val_dynptr(&ptr); 399 400 /* this should fail */ 401 bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0); 402 403 return 0; 404 } 405 406 /* A bpf_dynptr is invalidated if it's been written into */ 407 SEC("?raw_tp") 408 __failure __msg("Expected an initialized dynptr as arg #1") 409 int invalid_write1(void *ctx) 410 { 411 struct bpf_dynptr ptr; 412 void *data; 413 __u8 x = 0; 414 415 get_map_val_dynptr(&ptr); 416 417 memcpy(&ptr, &x, sizeof(x)); 418 419 /* this should fail */ 420 data = bpf_dynptr_data(&ptr, 0, 1); 421 422 return 0; 423 } 424 425 /* 426 * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed 427 * offset 428 */ 429 SEC("?raw_tp") 430 __failure __msg("cannot overwrite referenced dynptr") 431 int invalid_write2(void *ctx) 432 { 433 struct bpf_dynptr ptr; 434 char read_data[64]; 435 __u8 x = 0; 436 437 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); 438 439 memcpy((void *)&ptr + 8, &x, sizeof(x)); 440 441 /* this should fail */ 442 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); 443 444 bpf_ringbuf_submit_dynptr(&ptr, 0); 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 451 * non-const offset 452 */ 453 SEC("?raw_tp") 454 __failure __msg("cannot overwrite referenced dynptr") 455 int invalid_write3(void *ctx) 456 { 457 struct bpf_dynptr ptr; 458 char stack_buf[16]; 459 unsigned long len; 460 __u8 x = 0; 461 462 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr); 463 464 memcpy(stack_buf, &val, sizeof(val)); 465 len = stack_buf[0] & 0xf; 466 467 memcpy((void *)&ptr + len, &x, sizeof(x)); 468 469 /* this should fail */ 470 bpf_ringbuf_submit_dynptr(&ptr, 0); 471 472 return 0; 473 } 474 475 static int invalid_write4_callback(__u32 index, void *data) 476 { 477 *(__u32 *)data = 123; 478 479 return 0; 480 } 481 482 /* If the dynptr is written into in a callback function, it should 483 * be invalidated as a dynptr 484 */ 485 SEC("?raw_tp") 486 __failure __msg("cannot overwrite referenced dynptr") 487 int invalid_write4(void *ctx) 488 { 489 struct bpf_dynptr ptr; 490 491 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); 492 493 bpf_loop(10, invalid_write4_callback, &ptr, 0); 494 495 /* this should fail */ 496 bpf_ringbuf_submit_dynptr(&ptr, 0); 497 498 return 0; 499 } 500 501 /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */ 502 struct bpf_dynptr global_dynptr; 503 504 SEC("?raw_tp") 505 __failure __msg("type=map_value expected=fp") 506 int global(void *ctx) 507 { 508 /* this should fail */ 509 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr); 510 511 bpf_ringbuf_discard_dynptr(&global_dynptr, 0); 512 513 return 0; 514 } 515 516 /* A direct read should fail */ 517 SEC("?raw_tp") 518 __failure __msg("invalid read from stack") 519 int invalid_read1(void *ctx) 520 { 521 struct bpf_dynptr ptr; 522 523 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); 524 525 /* this should fail */ 526 val = *(int *)&ptr; 527 528 bpf_ringbuf_discard_dynptr(&ptr, 0); 529 530 return 0; 531 } 532 533 /* A direct read at an offset should fail */ 534 SEC("?raw_tp") 535 __failure __msg("cannot pass in dynptr at an offset") 536 int invalid_read2(void *ctx) 537 { 538 struct bpf_dynptr ptr; 539 char read_data[64]; 540 541 get_map_val_dynptr(&ptr); 542 543 /* this should fail */ 544 bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0); 545 546 return 0; 547 } 548 549 /* A direct read at an offset into the lower stack slot should fail */ 550 SEC("?raw_tp") 551 __failure __msg("invalid read from stack") 552 int invalid_read3(void *ctx) 553 { 554 struct bpf_dynptr ptr1, ptr2; 555 556 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1); 557 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2); 558 559 /* this should fail */ 560 memcpy(&val, (void *)&ptr1 + 8, sizeof(val)); 561 562 bpf_ringbuf_discard_dynptr(&ptr1, 0); 563 bpf_ringbuf_discard_dynptr(&ptr2, 0); 564 565 return 0; 566 } 567 568 static int invalid_read4_callback(__u32 index, void *data) 569 { 570 /* this should fail */ 571 val = *(__u32 *)data; 572 573 return 0; 574 } 575 576 /* A direct read within a callback function should fail */ 577 SEC("?raw_tp") 578 __failure __msg("invalid read from stack") 579 int invalid_read4(void *ctx) 580 { 581 struct bpf_dynptr ptr; 582 583 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); 584 585 bpf_loop(10, invalid_read4_callback, &ptr, 0); 586 587 bpf_ringbuf_submit_dynptr(&ptr, 0); 588 589 return 0; 590 } 591 592 /* Initializing a dynptr on an offset should fail */ 593 SEC("?raw_tp") 594 __failure __msg("cannot pass in dynptr at an offset=0") 595 int invalid_offset(void *ctx) 596 { 597 struct bpf_dynptr ptr; 598 599 /* this should fail */ 600 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1); 601 602 bpf_ringbuf_discard_dynptr(&ptr, 0); 603 604 return 0; 605 } 606 607 /* Can't release a dynptr twice */ 608 SEC("?raw_tp") 609 __failure __msg("arg 1 is an unacquired reference") 610 int release_twice(void *ctx) 611 { 612 struct bpf_dynptr ptr; 613 614 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr); 615 616 bpf_ringbuf_discard_dynptr(&ptr, 0); 617 618 /* this second release should fail */ 619 bpf_ringbuf_discard_dynptr(&ptr, 0); 620 621 return 0; 622 } 623 624 static int release_twice_callback_fn(__u32 index, void *data) 625 { 626 /* this should fail */ 627 bpf_ringbuf_discard_dynptr(data, 0); 628 629 return 0; 630 } 631 632 /* Test that releasing a dynptr twice, where one of the releases happens 633 * within a callback function, fails 634 */ 635 SEC("?raw_tp") 636 __failure __msg("arg 1 is an unacquired reference") 637 int release_twice_callback(void *ctx) 638 { 639 struct bpf_dynptr ptr; 640 641 bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr); 642 643 bpf_ringbuf_discard_dynptr(&ptr, 0); 644 645 bpf_loop(10, release_twice_callback_fn, &ptr, 0); 646 647 return 0; 648 } 649 650 /* Reject unsupported local mem types for dynptr_from_mem API */ 651 SEC("?raw_tp") 652 __failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data") 653 int dynptr_from_mem_invalid_api(void *ctx) 654 { 655 struct bpf_dynptr ptr; 656 int x = 0; 657 658 /* this should fail */ 659 bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr); 660 661 return 0; 662 } 663 664 SEC("?tc") 665 __failure __msg("cannot overwrite referenced dynptr") __log_level(2) 666 int dynptr_pruning_overwrite(struct __sk_buff *ctx) 667 { 668 asm volatile ( 669 "r9 = 0xeB9F; \ 670 r6 = %[ringbuf] ll; \ 671 r1 = r6; \ 672 r2 = 8; \ 673 r3 = 0; \ 674 r4 = r10; \ 675 r4 += -16; \ 676 call %[bpf_ringbuf_reserve_dynptr]; \ 677 if r0 == 0 goto pjmp1; \ 678 goto pjmp2; \ 679 pjmp1: \ 680 *(u64 *)(r10 - 16) = r9; \ 681 pjmp2: \ 682 r1 = r10; \ 683 r1 += -16; \ 684 r2 = 0; \ 685 call %[bpf_ringbuf_discard_dynptr]; " 686 : 687 : __imm(bpf_ringbuf_reserve_dynptr), 688 __imm(bpf_ringbuf_discard_dynptr), 689 __imm_addr(ringbuf) 690 : __clobber_all 691 ); 692 return 0; 693 } 694 695 SEC("?tc") 696 __success __msg("12: safe") __log_level(2) 697 int dynptr_pruning_stacksafe(struct __sk_buff *ctx) 698 { 699 asm volatile ( 700 "r9 = 0xeB9F; \ 701 r6 = %[ringbuf] ll; \ 702 r1 = r6; \ 703 r2 = 8; \ 704 r3 = 0; \ 705 r4 = r10; \ 706 r4 += -16; \ 707 call %[bpf_ringbuf_reserve_dynptr]; \ 708 if r0 == 0 goto stjmp1; \ 709 goto stjmp2; \ 710 stjmp1: \ 711 r9 = r9; \ 712 stjmp2: \ 713 r1 = r10; \ 714 r1 += -16; \ 715 r2 = 0; \ 716 call %[bpf_ringbuf_discard_dynptr]; " 717 : 718 : __imm(bpf_ringbuf_reserve_dynptr), 719 __imm(bpf_ringbuf_discard_dynptr), 720 __imm_addr(ringbuf) 721 : __clobber_all 722 ); 723 return 0; 724 } 725 726 SEC("?tc") 727 __failure __msg("cannot overwrite referenced dynptr") __log_level(2) 728 int dynptr_pruning_type_confusion(struct __sk_buff *ctx) 729 { 730 asm volatile ( 731 "r6 = %[array_map4] ll; \ 732 r7 = %[ringbuf] ll; \ 733 r1 = r6; \ 734 r2 = r10; \ 735 r2 += -8; \ 736 r9 = 0; \ 737 *(u64 *)(r2 + 0) = r9; \ 738 r3 = r10; \ 739 r3 += -24; \ 740 r9 = 0xeB9FeB9F; \ 741 *(u64 *)(r10 - 16) = r9; \ 742 *(u64 *)(r10 - 24) = r9; \ 743 r9 = 0; \ 744 r4 = 0; \ 745 r8 = r2; \ 746 call %[bpf_map_update_elem]; \ 747 r1 = r6; \ 748 r2 = r8; \ 749 call %[bpf_map_lookup_elem]; \ 750 if r0 != 0 goto tjmp1; \ 751 exit; \ 752 tjmp1: \ 753 r8 = r0; \ 754 r1 = r7; \ 755 r2 = 8; \ 756 r3 = 0; \ 757 r4 = r10; \ 758 r4 += -16; \ 759 r0 = *(u64 *)(r0 + 0); \ 760 call %[bpf_ringbuf_reserve_dynptr]; \ 761 if r0 == 0 goto tjmp2; \ 762 r8 = r8; \ 763 r8 = r8; \ 764 r8 = r8; \ 765 r8 = r8; \ 766 r8 = r8; \ 767 r8 = r8; \ 768 r8 = r8; \ 769 goto tjmp3; \ 770 tjmp2: \ 771 *(u64 *)(r10 - 8) = r9; \ 772 *(u64 *)(r10 - 16) = r9; \ 773 r1 = r8; \ 774 r1 += 8; \ 775 r2 = 0; \ 776 r3 = 0; \ 777 r4 = r10; \ 778 r4 += -16; \ 779 call %[bpf_dynptr_from_mem]; \ 780 tjmp3: \ 781 r1 = r10; \ 782 r1 += -16; \ 783 r2 = 0; \ 784 call %[bpf_ringbuf_discard_dynptr]; " 785 : 786 : __imm(bpf_map_update_elem), 787 __imm(bpf_map_lookup_elem), 788 __imm(bpf_ringbuf_reserve_dynptr), 789 __imm(bpf_dynptr_from_mem), 790 __imm(bpf_ringbuf_discard_dynptr), 791 __imm_addr(array_map4), 792 __imm_addr(ringbuf) 793 : __clobber_all 794 ); 795 return 0; 796 } 797 798 SEC("?tc") 799 __failure __msg("dynptr has to be at a constant offset") __log_level(2) 800 int dynptr_var_off_overwrite(struct __sk_buff *ctx) 801 { 802 asm volatile ( 803 "r9 = 16; \ 804 *(u32 *)(r10 - 4) = r9; \ 805 r8 = *(u32 *)(r10 - 4); \ 806 if r8 >= 0 goto vjmp1; \ 807 r0 = 1; \ 808 exit; \ 809 vjmp1: \ 810 if r8 <= 16 goto vjmp2; \ 811 r0 = 1; \ 812 exit; \ 813 vjmp2: \ 814 r8 &= 16; \ 815 r1 = %[ringbuf] ll; \ 816 r2 = 8; \ 817 r3 = 0; \ 818 r4 = r10; \ 819 r4 += -32; \ 820 r4 += r8; \ 821 call %[bpf_ringbuf_reserve_dynptr]; \ 822 r9 = 0xeB9F; \ 823 *(u64 *)(r10 - 16) = r9; \ 824 r1 = r10; \ 825 r1 += -32; \ 826 r1 += r8; \ 827 r2 = 0; \ 828 call %[bpf_ringbuf_discard_dynptr]; " 829 : 830 : __imm(bpf_ringbuf_reserve_dynptr), 831 __imm(bpf_ringbuf_discard_dynptr), 832 __imm_addr(ringbuf) 833 : __clobber_all 834 ); 835 return 0; 836 } 837 838 SEC("?tc") 839 __failure __msg("cannot overwrite referenced dynptr") __log_level(2) 840 int dynptr_partial_slot_invalidate(struct __sk_buff *ctx) 841 { 842 asm volatile ( 843 "r6 = %[ringbuf] ll; \ 844 r7 = %[array_map4] ll; \ 845 r1 = r7; \ 846 r2 = r10; \ 847 r2 += -8; \ 848 r9 = 0; \ 849 *(u64 *)(r2 + 0) = r9; \ 850 r3 = r2; \ 851 r4 = 0; \ 852 r8 = r2; \ 853 call %[bpf_map_update_elem]; \ 854 r1 = r7; \ 855 r2 = r8; \ 856 call %[bpf_map_lookup_elem]; \ 857 if r0 != 0 goto sjmp1; \ 858 exit; \ 859 sjmp1: \ 860 r7 = r0; \ 861 r1 = r6; \ 862 r2 = 8; \ 863 r3 = 0; \ 864 r4 = r10; \ 865 r4 += -24; \ 866 call %[bpf_ringbuf_reserve_dynptr]; \ 867 *(u64 *)(r10 - 16) = r9; \ 868 r1 = r7; \ 869 r2 = 8; \ 870 r3 = 0; \ 871 r4 = r10; \ 872 r4 += -16; \ 873 call %[bpf_dynptr_from_mem]; \ 874 r1 = r10; \ 875 r1 += -512; \ 876 r2 = 488; \ 877 r3 = r10; \ 878 r3 += -24; \ 879 r4 = 0; \ 880 r5 = 0; \ 881 call %[bpf_dynptr_read]; \ 882 r8 = 1; \ 883 if r0 != 0 goto sjmp2; \ 884 r8 = 0; \ 885 sjmp2: \ 886 r1 = r10; \ 887 r1 += -24; \ 888 r2 = 0; \ 889 call %[bpf_ringbuf_discard_dynptr]; " 890 : 891 : __imm(bpf_map_update_elem), 892 __imm(bpf_map_lookup_elem), 893 __imm(bpf_ringbuf_reserve_dynptr), 894 __imm(bpf_ringbuf_discard_dynptr), 895 __imm(bpf_dynptr_from_mem), 896 __imm(bpf_dynptr_read), 897 __imm_addr(ringbuf), 898 __imm_addr(array_map4) 899 : __clobber_all 900 ); 901 return 0; 902 } 903 904 /* Test that it is allowed to overwrite unreferenced dynptr. */ 905 SEC("?raw_tp") 906 __success 907 int dynptr_overwrite_unref(void *ctx) 908 { 909 struct bpf_dynptr ptr; 910 911 if (get_map_val_dynptr(&ptr)) 912 return 0; 913 if (get_map_val_dynptr(&ptr)) 914 return 0; 915 if (get_map_val_dynptr(&ptr)) 916 return 0; 917 918 return 0; 919 } 920 921 /* Test that slices are invalidated on reinitializing a dynptr. */ 922 SEC("?raw_tp") 923 __failure __msg("invalid mem access 'scalar'") 924 int dynptr_invalidate_slice_reinit(void *ctx) 925 { 926 struct bpf_dynptr ptr; 927 __u8 *p; 928 929 if (get_map_val_dynptr(&ptr)) 930 return 0; 931 p = bpf_dynptr_data(&ptr, 0, 1); 932 if (!p) 933 return 0; 934 if (get_map_val_dynptr(&ptr)) 935 return 0; 936 /* this should fail */ 937 return *p; 938 } 939 940 /* Invalidation of dynptr slices on destruction of dynptr should not miss 941 * mem_or_null pointers. 942 */ 943 SEC("?raw_tp") 944 __failure __msg("R1 type=scalar expected=percpu_ptr_") 945 int dynptr_invalidate_slice_or_null(void *ctx) 946 { 947 struct bpf_dynptr ptr; 948 __u8 *p; 949 950 if (get_map_val_dynptr(&ptr)) 951 return 0; 952 953 p = bpf_dynptr_data(&ptr, 0, 1); 954 *(__u8 *)&ptr = 0; 955 /* this should fail */ 956 bpf_this_cpu_ptr(p); 957 return 0; 958 } 959 960 /* Destruction of dynptr should also any slices obtained from it */ 961 SEC("?raw_tp") 962 __failure __msg("R7 invalid mem access 'scalar'") 963 int dynptr_invalidate_slice_failure(void *ctx) 964 { 965 struct bpf_dynptr ptr1; 966 struct bpf_dynptr ptr2; 967 __u8 *p1, *p2; 968 969 if (get_map_val_dynptr(&ptr1)) 970 return 0; 971 if (get_map_val_dynptr(&ptr2)) 972 return 0; 973 974 p1 = bpf_dynptr_data(&ptr1, 0, 1); 975 if (!p1) 976 return 0; 977 p2 = bpf_dynptr_data(&ptr2, 0, 1); 978 if (!p2) 979 return 0; 980 981 *(__u8 *)&ptr1 = 0; 982 /* this should fail */ 983 return *p1; 984 } 985 986 /* Invalidation of slices should be scoped and should not prevent dereferencing 987 * slices of another dynptr after destroying unrelated dynptr 988 */ 989 SEC("?raw_tp") 990 __success 991 int dynptr_invalidate_slice_success(void *ctx) 992 { 993 struct bpf_dynptr ptr1; 994 struct bpf_dynptr ptr2; 995 __u8 *p1, *p2; 996 997 if (get_map_val_dynptr(&ptr1)) 998 return 1; 999 if (get_map_val_dynptr(&ptr2)) 1000 return 1; 1001 1002 p1 = bpf_dynptr_data(&ptr1, 0, 1); 1003 if (!p1) 1004 return 1; 1005 p2 = bpf_dynptr_data(&ptr2, 0, 1); 1006 if (!p2) 1007 return 1; 1008 1009 *(__u8 *)&ptr1 = 0; 1010 return *p2; 1011 } 1012 1013 /* Overwriting referenced dynptr should be rejected */ 1014 SEC("?raw_tp") 1015 __failure __msg("cannot overwrite referenced dynptr") 1016 int dynptr_overwrite_ref(void *ctx) 1017 { 1018 struct bpf_dynptr ptr; 1019 1020 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr); 1021 /* this should fail */ 1022 if (get_map_val_dynptr(&ptr)) 1023 bpf_ringbuf_discard_dynptr(&ptr, 0); 1024 return 0; 1025 } 1026 1027 /* Reject writes to dynptr slot from bpf_dynptr_read */ 1028 SEC("?raw_tp") 1029 __failure __msg("potential write to dynptr at off=-16") 1030 int dynptr_read_into_slot(void *ctx) 1031 { 1032 union { 1033 struct { 1034 char _pad[48]; 1035 struct bpf_dynptr ptr; 1036 }; 1037 char buf[64]; 1038 } data; 1039 1040 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr); 1041 /* this should fail */ 1042 bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0); 1043 1044 return 0; 1045 } 1046 1047 /* Reject writes to dynptr slot for uninit arg */ 1048 SEC("?raw_tp") 1049 __failure __msg("potential write to dynptr at off=-16") 1050 int uninit_write_into_slot(void *ctx) 1051 { 1052 struct { 1053 char buf[64]; 1054 struct bpf_dynptr ptr; 1055 } data; 1056 1057 bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr); 1058 /* this should fail */ 1059 bpf_get_current_comm(data.buf, 80); 1060 1061 return 0; 1062 } 1063 1064 static int callback(__u32 index, void *data) 1065 { 1066 *(__u32 *)data = 123; 1067 1068 return 0; 1069 } 1070 1071 /* If the dynptr is written into in a callback function, its data 1072 * slices should be invalidated as well. 1073 */ 1074 SEC("?raw_tp") 1075 __failure __msg("invalid mem access 'scalar'") 1076 int invalid_data_slices(void *ctx) 1077 { 1078 struct bpf_dynptr ptr; 1079 __u32 *slice; 1080 1081 if (get_map_val_dynptr(&ptr)) 1082 return 0; 1083 1084 slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32)); 1085 if (!slice) 1086 return 0; 1087 1088 bpf_loop(10, callback, &ptr, 0); 1089 1090 /* this should fail */ 1091 *slice = 1; 1092 1093 return 0; 1094 } 1095