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