Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 862 lines 21 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/ctx.c */ 3 4#include "vmlinux.h" 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7#include "../test_kmods/bpf_testmod_kfunc.h" 8 9static const char ctx_strncmp_target[] = "ctx"; 10static const char ctx_snprintf_fmt[] = ""; 11 12SEC("tc") 13__description("context stores via BPF_ATOMIC") 14__failure __msg("BPF_ATOMIC stores into R1 ctx is not allowed") 15__naked void context_stores_via_bpf_atomic(void) 16{ 17 asm volatile (" \ 18 r0 = 0; \ 19 lock *(u32 *)(r1 + %[__sk_buff_mark]) += w0; \ 20 exit; \ 21" : 22 : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 23 : __clobber_all); 24} 25 26SEC("tc") 27__description("arithmetic ops make PTR_TO_CTX unusable") 28__failure __msg("dereference of modified ctx ptr") 29__naked void make_ptr_to_ctx_unusable(void) 30{ 31 asm volatile (" \ 32 r1 += %[__imm_0]; \ 33 r0 = *(u32*)(r1 + %[__sk_buff_mark]); \ 34 exit; \ 35" : 36 : __imm_const(__imm_0, 37 offsetof(struct __sk_buff, data) - offsetof(struct __sk_buff, mark)), 38 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 39 : __clobber_all); 40} 41 42SEC("tc") 43__description("pass unmodified ctx pointer to helper") 44__success __retval(0) 45__naked void unmodified_ctx_pointer_to_helper(void) 46{ 47 asm volatile (" \ 48 r2 = 0; \ 49 call %[bpf_csum_update]; \ 50 r0 = 0; \ 51 exit; \ 52" : 53 : __imm(bpf_csum_update) 54 : __clobber_all); 55} 56 57SEC("tc") 58__description("pass modified ctx pointer to helper, 1") 59__failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 60__naked void ctx_pointer_to_helper_1(void) 61{ 62 asm volatile (" \ 63 r1 += -612; \ 64 r2 = 0; \ 65 call %[bpf_csum_update]; \ 66 r0 = 0; \ 67 exit; \ 68" : 69 : __imm(bpf_csum_update) 70 : __clobber_all); 71} 72 73SEC("socket") 74__description("pass modified ctx pointer to helper, 2") 75__failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 76__naked void ctx_pointer_to_helper_2(void) 77{ 78 asm volatile (" \ 79 r1 += -612; \ 80 call %[bpf_get_socket_cookie]; \ 81 r0 = 0; \ 82 exit; \ 83" : 84 : __imm(bpf_get_socket_cookie) 85 : __clobber_all); 86} 87 88SEC("tc") 89__description("pass modified ctx pointer to helper, 3") 90__failure __msg("variable ctx access var_off=(0x0; 0x4)") 91__naked void ctx_pointer_to_helper_3(void) 92{ 93 asm volatile (" \ 94 r3 = *(u32*)(r1 + 0); \ 95 r3 &= 4; \ 96 r1 += r3; \ 97 r2 = 0; \ 98 call %[bpf_csum_update]; \ 99 r0 = 0; \ 100 exit; \ 101" : 102 : __imm(bpf_csum_update) 103 : __clobber_all); 104} 105 106SEC("cgroup/sendmsg6") 107__description("pass ctx or null check, 1: ctx") 108__success 109__naked void or_null_check_1_ctx(void) 110{ 111 asm volatile (" \ 112 call %[bpf_get_netns_cookie]; \ 113 r0 = 0; \ 114 exit; \ 115" : 116 : __imm(bpf_get_netns_cookie) 117 : __clobber_all); 118} 119 120SEC("cgroup/sendmsg6") 121__description("pass ctx or null check, 2: null") 122__success 123__naked void or_null_check_2_null(void) 124{ 125 asm volatile (" \ 126 r1 = 0; \ 127 call %[bpf_get_netns_cookie]; \ 128 r0 = 0; \ 129 exit; \ 130" : 131 : __imm(bpf_get_netns_cookie) 132 : __clobber_all); 133} 134 135SEC("cgroup/sendmsg6") 136__description("pass ctx or null check, 3: 1") 137__failure __msg("R1 type=scalar expected=ctx") 138__naked void or_null_check_3_1(void) 139{ 140 asm volatile (" \ 141 r1 = 1; \ 142 call %[bpf_get_netns_cookie]; \ 143 r0 = 0; \ 144 exit; \ 145" : 146 : __imm(bpf_get_netns_cookie) 147 : __clobber_all); 148} 149 150SEC("cgroup/sendmsg6") 151__description("pass ctx or null check, 4: ctx - const") 152__failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 153__naked void null_check_4_ctx_const(void) 154{ 155 asm volatile (" \ 156 r1 += -612; \ 157 call %[bpf_get_netns_cookie]; \ 158 r0 = 0; \ 159 exit; \ 160" : 161 : __imm(bpf_get_netns_cookie) 162 : __clobber_all); 163} 164 165SEC("cgroup/connect4") 166__description("pass ctx or null check, 5: null (connect)") 167__success 168__naked void null_check_5_null_connect(void) 169{ 170 asm volatile (" \ 171 r1 = 0; \ 172 call %[bpf_get_netns_cookie]; \ 173 r0 = 0; \ 174 exit; \ 175" : 176 : __imm(bpf_get_netns_cookie) 177 : __clobber_all); 178} 179 180SEC("cgroup/post_bind4") 181__description("pass ctx or null check, 6: null (bind)") 182__success 183__naked void null_check_6_null_bind(void) 184{ 185 asm volatile (" \ 186 r1 = 0; \ 187 call %[bpf_get_netns_cookie]; \ 188 r0 = 0; \ 189 exit; \ 190" : 191 : __imm(bpf_get_netns_cookie) 192 : __clobber_all); 193} 194 195SEC("cgroup/post_bind4") 196__description("pass ctx or null check, 7: ctx (bind)") 197__success 198__naked void null_check_7_ctx_bind(void) 199{ 200 asm volatile (" \ 201 call %[bpf_get_socket_cookie]; \ 202 r0 = 0; \ 203 exit; \ 204" : 205 : __imm(bpf_get_socket_cookie) 206 : __clobber_all); 207} 208 209SEC("cgroup/post_bind4") 210__description("pass ctx or null check, 8: null (bind)") 211__failure __msg("R1 type=scalar expected=ctx") 212__naked void null_check_8_null_bind(void) 213{ 214 asm volatile (" \ 215 r1 = 0; \ 216 call %[bpf_get_socket_cookie]; \ 217 r0 = 0; \ 218 exit; \ 219" : 220 : __imm(bpf_get_socket_cookie) 221 : __clobber_all); 222} 223 224#define narrow_load(type, ctx, field) \ 225 SEC(type) \ 226 __description("narrow load on field " #field " of " #ctx) \ 227 __failure __msg("invalid bpf_context access") \ 228 __naked void invalid_narrow_load##ctx##field(void) \ 229 { \ 230 asm volatile (" \ 231 r1 = *(u32 *)(r1 + %[off]); \ 232 r0 = 0; \ 233 exit;" \ 234 : \ 235 : __imm_const(off, offsetof(struct ctx, field) + 4) \ 236 : __clobber_all); \ 237 } 238 239narrow_load("cgroup/getsockopt", bpf_sockopt, sk); 240narrow_load("cgroup/getsockopt", bpf_sockopt, optval); 241narrow_load("cgroup/getsockopt", bpf_sockopt, optval_end); 242narrow_load("tc", __sk_buff, sk); 243narrow_load("cgroup/bind4", bpf_sock_addr, sk); 244narrow_load("sockops", bpf_sock_ops, sk); 245narrow_load("sockops", bpf_sock_ops, skb_data); 246narrow_load("sockops", bpf_sock_ops, skb_data_end); 247narrow_load("sockops", bpf_sock_ops, skb_hwtstamp); 248 249#define unaligned_access(type, ctx, field) \ 250 SEC(type) \ 251 __description("unaligned access on field " #field " of " #ctx) \ 252 __failure __msg("invalid bpf_context access") \ 253 __naked void unaligned_ctx_access_##ctx##field(void) \ 254 { \ 255 asm volatile (" \ 256 r1 = *(u%[size] *)(r1 + %[off]); \ 257 r0 = 0; \ 258 exit;" \ 259 : \ 260 : __imm_const(size, sizeof_field(struct ctx, field) * 8), \ 261 __imm_const(off, offsetof(struct ctx, field) + 1) \ 262 : __clobber_all); \ 263 } 264 265unaligned_access("flow_dissector", __sk_buff, data); 266unaligned_access("netfilter", bpf_nf_ctx, skb); 267 268#define padding_access(type, ctx, prev_field, sz) \ 269 SEC(type) \ 270 __description("access on " #ctx " padding after " #prev_field) \ 271 __naked void padding_ctx_access_##ctx(void) \ 272 { \ 273 asm volatile (" \ 274 r1 = *(u%[size] *)(r1 + %[off]); \ 275 r0 = 0; \ 276 exit;" \ 277 : \ 278 : __imm_const(size, sz * 8), \ 279 __imm_const(off, offsetofend(struct ctx, prev_field)) \ 280 : __clobber_all); \ 281 } 282 283__failure __msg("invalid bpf_context access") 284padding_access("cgroup/bind4", bpf_sock_addr, msg_src_ip6[3], 4); 285 286__success 287padding_access("sk_lookup", bpf_sk_lookup, remote_port, 2); 288 289__failure __msg("invalid bpf_context access") 290padding_access("tc", __sk_buff, tstamp_type, 2); 291 292__failure __msg("invalid bpf_context access") 293padding_access("cgroup/post_bind4", bpf_sock, dst_port, 2); 294 295__failure __msg("invalid bpf_context access") 296padding_access("sk_reuseport", sk_reuseport_md, hash, 4); 297 298SEC("?syscall") 299__description("syscall: write to ctx with fixed offset") 300__success 301int syscall_ctx_fixed_off_write(void *ctx) 302{ 303 char *p = ctx; 304 305 *(__u32 *)p = 0; 306 *(__u32 *)(p + 4) = 0; 307 return 0; 308} 309 310SEC("?syscall") 311__description("syscall: read ctx with fixed offset") 312__success 313int syscall_ctx_fixed_off_read(void *ctx) 314{ 315 char *p = ctx; 316 volatile __u32 val; 317 318 val = *(__u32 *)(p + 4); 319 (void)val; 320 return 0; 321} 322 323SEC("?syscall") 324__description("syscall: unaligned read ctx with fixed offset") 325__success 326int syscall_ctx_unaligned_fixed_off_read(void *ctx) 327{ 328 char *p = ctx; 329 volatile __u32 val; 330 331 val = *(__u32 *)(p + 2); 332 (void)val; 333 return 0; 334} 335 336SEC("?syscall") 337__description("syscall: unaligned write ctx with fixed offset") 338__success 339int syscall_ctx_unaligned_fixed_off_write(void *ctx) 340{ 341 char *p = ctx; 342 343 *(__u32 *)(p + 2) = 0; 344 return 0; 345} 346 347SEC("?syscall") 348__description("syscall: read ctx with variable offset") 349__success 350int syscall_ctx_var_off_read(void *ctx) 351{ 352 __u64 off = bpf_get_prandom_u32(); 353 char *p = ctx; 354 volatile __u32 val; 355 356 off &= 0xfc; 357 p += off; 358 val = *(__u32 *)p; 359 (void)val; 360 return 0; 361} 362 363SEC("?syscall") 364__description("syscall: write ctx with variable offset") 365__success 366int syscall_ctx_var_off_write(void *ctx) 367{ 368 __u64 off = bpf_get_prandom_u32(); 369 char *p = ctx; 370 371 off &= 0xfc; 372 p += off; 373 *(__u32 *)p = 0; 374 return 0; 375} 376 377SEC("?syscall") 378__description("syscall: unaligned read ctx with variable offset") 379__success 380int syscall_ctx_unaligned_var_off_read(void *ctx) 381{ 382 __u64 off = bpf_get_prandom_u32(); 383 char *p = ctx; 384 volatile __u32 val; 385 386 off &= 0xfc; 387 off += 2; 388 p += off; 389 val = *(__u32 *)p; 390 (void)val; 391 return 0; 392} 393 394SEC("?syscall") 395__description("syscall: unaligned write ctx with variable offset") 396__success 397int syscall_ctx_unaligned_var_off_write(void *ctx) 398{ 399 __u64 off = bpf_get_prandom_u32(); 400 char *p = ctx; 401 402 off &= 0xfc; 403 off += 2; 404 p += off; 405 *(__u32 *)p = 0; 406 return 0; 407} 408 409SEC("?syscall") 410__description("syscall: reject ctx access past U16_MAX with fixed offset") 411__failure __msg("outside of the allowed memory range") 412int syscall_ctx_u16_max_fixed_off(void *ctx) 413{ 414 char *p = ctx; 415 volatile __u32 val; 416 417 p += 65535; 418 val = *(__u32 *)p; 419 (void)val; 420 return 0; 421} 422 423SEC("?syscall") 424__description("syscall: reject ctx access past U16_MAX with variable offset") 425__failure __msg("outside of the allowed memory range") 426int syscall_ctx_u16_max_var_off(void *ctx) 427{ 428 __u64 off = bpf_get_prandom_u32(); 429 char *p = ctx; 430 volatile __u32 val; 431 432 off &= 0xffff; 433 off += 1; 434 p += off; 435 val = *(__u32 *)p; 436 (void)val; 437 return 0; 438} 439 440SEC("?syscall") 441__description("syscall: reject negative variable offset ctx access") 442__failure __msg("min value is negative") 443int syscall_ctx_neg_var_off(void *ctx) 444{ 445 __u64 off = bpf_get_prandom_u32(); 446 char *p = ctx; 447 448 off &= 4; 449 p -= off; 450 return *(__u32 *)p; 451} 452 453SEC("?syscall") 454__description("syscall: reject unbounded variable offset ctx access") 455__failure __msg("unbounded memory access") 456int syscall_ctx_unbounded_var_off(void *ctx) 457{ 458 __u64 off = (__u32)bpf_get_prandom_u32(); 459 char *p = ctx; 460 461 off <<= 2; 462 p += off; 463 return *(__u32 *)p; 464} 465 466SEC("?syscall") 467__description("syscall: helper read ctx with fixed offset") 468__success 469int syscall_ctx_helper_fixed_off_read(void *ctx) 470{ 471 char *p = ctx; 472 473 p += 4; 474 return bpf_strncmp(p, 4, ctx_strncmp_target); 475} 476 477SEC("?syscall") 478__description("syscall: helper write ctx with fixed offset") 479__success 480int syscall_ctx_helper_fixed_off_write(void *ctx) 481{ 482 char *p = ctx; 483 484 p += 4; 485 return bpf_probe_read_kernel(p, 4, 0); 486} 487 488SEC("?syscall") 489__description("syscall: helper unaligned read ctx with fixed offset") 490__success 491int syscall_ctx_helper_unaligned_fixed_off_read(void *ctx) 492{ 493 char *p = ctx; 494 495 p += 2; 496 return bpf_strncmp(p, 4, ctx_strncmp_target); 497} 498 499SEC("?syscall") 500__description("syscall: helper unaligned write ctx with fixed offset") 501__success 502int syscall_ctx_helper_unaligned_fixed_off_write(void *ctx) 503{ 504 char *p = ctx; 505 506 p += 2; 507 return bpf_probe_read_kernel(p, 4, 0); 508} 509 510SEC("?syscall") 511__description("syscall: helper read ctx with variable offset") 512__success 513int syscall_ctx_helper_var_off_read(void *ctx) 514{ 515 __u64 off = bpf_get_prandom_u32(); 516 char *p = ctx; 517 518 off &= 0xfc; 519 p += off; 520 return bpf_strncmp(p, 4, ctx_strncmp_target); 521} 522 523SEC("?syscall") 524__description("syscall: helper write ctx with variable offset") 525__success 526int syscall_ctx_helper_var_off_write(void *ctx) 527{ 528 __u64 off = bpf_get_prandom_u32(); 529 char *p = ctx; 530 531 off &= 0xfc; 532 p += off; 533 return bpf_probe_read_kernel(p, 4, 0); 534} 535 536SEC("?syscall") 537__description("syscall: helper unaligned read ctx with variable offset") 538__success 539int syscall_ctx_helper_unaligned_var_off_read(void *ctx) 540{ 541 __u64 off = bpf_get_prandom_u32(); 542 char *p = ctx; 543 544 off &= 0xfc; 545 off += 2; 546 p += off; 547 return bpf_strncmp(p, 4, ctx_strncmp_target); 548} 549 550SEC("?syscall") 551__description("syscall: helper unaligned write ctx with variable offset") 552__success 553int syscall_ctx_helper_unaligned_var_off_write(void *ctx) 554{ 555 __u64 off = bpf_get_prandom_u32(); 556 char *p = ctx; 557 558 off &= 0xfc; 559 off += 2; 560 p += off; 561 return bpf_probe_read_kernel(p, 4, 0); 562} 563 564SEC("?syscall") 565__description("syscall: reject helper read ctx past U16_MAX with fixed offset") 566__failure __msg("outside of the allowed memory range") 567int syscall_ctx_helper_u16_max_fixed_off_read(void *ctx) 568{ 569 char *p = ctx; 570 571 p += 65535; 572 return bpf_strncmp(p, 4, ctx_strncmp_target); 573} 574 575SEC("?syscall") 576__description("syscall: reject helper write ctx past U16_MAX with fixed offset") 577__failure __msg("outside of the allowed memory range") 578int syscall_ctx_helper_u16_max_fixed_off_write(void *ctx) 579{ 580 char *p = ctx; 581 582 p += 65535; 583 return bpf_probe_read_kernel(p, 4, 0); 584} 585 586SEC("?syscall") 587__description("syscall: reject helper read ctx past U16_MAX with variable offset") 588__failure __msg("outside of the allowed memory range") 589int syscall_ctx_helper_u16_max_var_off_read(void *ctx) 590{ 591 __u64 off = bpf_get_prandom_u32(); 592 char *p = ctx; 593 594 off &= 0xffff; 595 off += 1; 596 p += off; 597 return bpf_strncmp(p, 4, ctx_strncmp_target); 598} 599 600SEC("?syscall") 601__description("syscall: reject helper write ctx past U16_MAX with variable offset") 602__failure __msg("outside of the allowed memory range") 603int syscall_ctx_helper_u16_max_var_off_write(void *ctx) 604{ 605 __u64 off = bpf_get_prandom_u32(); 606 char *p = ctx; 607 608 off &= 0xffff; 609 off += 1; 610 p += off; 611 return bpf_probe_read_kernel(p, 4, 0); 612} 613 614SEC("?syscall") 615__description("syscall: helper read zero-sized ctx access") 616__success 617int syscall_ctx_helper_zero_sized_read(void *ctx) 618{ 619 return bpf_snprintf(0, 0, ctx_snprintf_fmt, ctx, 0); 620} 621 622SEC("?syscall") 623__description("syscall: helper write zero-sized ctx access") 624__success 625int syscall_ctx_helper_zero_sized_write(void *ctx) 626{ 627 return bpf_probe_read_kernel(ctx, 0, 0); 628} 629 630SEC("?syscall") 631__description("syscall: kfunc access ctx with fixed offset") 632__success 633int syscall_ctx_kfunc_fixed_off(void *ctx) 634{ 635 char *p = ctx; 636 637 p += 4; 638 bpf_kfunc_call_test_mem_len_pass1(p, 4); 639 return 0; 640} 641 642SEC("?syscall") 643__description("syscall: kfunc access ctx with variable offset") 644__success 645int syscall_ctx_kfunc_var_off(void *ctx) 646{ 647 __u64 off = bpf_get_prandom_u32(); 648 char *p = ctx; 649 650 off &= 0xfc; 651 p += off; 652 bpf_kfunc_call_test_mem_len_pass1(p, 4); 653 return 0; 654} 655 656SEC("?syscall") 657__description("syscall: kfunc unaligned access ctx with fixed offset") 658__success 659int syscall_ctx_kfunc_unaligned_fixed_off(void *ctx) 660{ 661 char *p = ctx; 662 663 p += 2; 664 bpf_kfunc_call_test_mem_len_pass1(p, 4); 665 return 0; 666} 667 668SEC("?syscall") 669__description("syscall: kfunc unaligned access ctx with variable offset") 670__success 671int syscall_ctx_kfunc_unaligned_var_off(void *ctx) 672{ 673 __u64 off = bpf_get_prandom_u32(); 674 char *p = ctx; 675 676 off &= 0xfc; 677 off += 2; 678 p += off; 679 bpf_kfunc_call_test_mem_len_pass1(p, 4); 680 return 0; 681} 682 683SEC("?syscall") 684__description("syscall: reject kfunc ctx access past U16_MAX with fixed offset") 685__failure __msg("outside of the allowed memory range") 686int syscall_ctx_kfunc_u16_max_fixed_off(void *ctx) 687{ 688 char *p = ctx; 689 690 p += 65535; 691 bpf_kfunc_call_test_mem_len_pass1(p, 4); 692 return 0; 693} 694 695SEC("?syscall") 696__description("syscall: reject kfunc ctx access past U16_MAX with variable offset") 697__failure __msg("outside of the allowed memory range") 698int syscall_ctx_kfunc_u16_max_var_off(void *ctx) 699{ 700 __u64 off = bpf_get_prandom_u32(); 701 char *p = ctx; 702 703 off &= 0xffff; 704 off += 1; 705 p += off; 706 bpf_kfunc_call_test_mem_len_pass1(p, 4); 707 return 0; 708} 709 710SEC("?syscall") 711__description("syscall: kfunc access zero-sized ctx") 712__success 713int syscall_ctx_kfunc_zero_sized(void *ctx) 714{ 715 bpf_kfunc_call_test_mem_len_pass1(ctx, 0); 716 return 0; 717} 718 719/* 720 * For non-syscall program types without convert_ctx_access, direct ctx 721 * dereference is still allowed after adding a fixed offset, while variable 722 * and negative direct accesses reject. 723 * 724 * Passing ctx as a helper or kfunc memory argument is only permitted for 725 * syscall programs, so the helper and kfunc cases below validate rejection 726 * for non-syscall ctx pointers at fixed, variable, and zero-sized accesses. 727 */ 728#define no_rewrite_ctx_access(type, name, off, load_t) \ 729 SEC("?" type) \ 730 __description(type ": read ctx at fixed offset") \ 731 __success \ 732 int no_rewrite_##name##_fixed(void *ctx) \ 733 { \ 734 char *p = ctx; \ 735 volatile load_t val; \ 736 \ 737 val = *(load_t *)(p + off); \ 738 (void)val; \ 739 return 0; \ 740 } \ 741 SEC("?" type) \ 742 __description(type ": reject variable offset ctx access") \ 743 __failure __msg("variable ctx access var_off=") \ 744 int no_rewrite_##name##_var(void *ctx) \ 745 { \ 746 __u64 off_var = bpf_get_prandom_u32(); \ 747 char *p = ctx; \ 748 \ 749 off_var &= 4; \ 750 p += off_var; \ 751 return *(load_t *)p; \ 752 } \ 753 SEC("?" type) \ 754 __description(type ": reject negative offset ctx access") \ 755 __failure __msg("invalid bpf_context access") \ 756 int no_rewrite_##name##_neg(void *ctx) \ 757 { \ 758 char *p = ctx; \ 759 \ 760 p -= 612; \ 761 return *(load_t *)p; \ 762 } \ 763 SEC("?" type) \ 764 __description(type ": reject helper read ctx at fixed offset") \ 765 __failure __msg("dereference of modified ctx ptr") \ 766 int no_rewrite_##name##_helper_read_fixed(void *ctx) \ 767 { \ 768 char *p = ctx; \ 769 \ 770 p += off; \ 771 return bpf_strncmp(p, 4, ctx_strncmp_target); \ 772 } \ 773 SEC("?" type) \ 774 __description(type ": reject helper write ctx at fixed offset") \ 775 __failure __msg("dereference of modified ctx ptr") \ 776 int no_rewrite_##name##_helper_write_fixed(void *ctx) \ 777 { \ 778 char *p = ctx; \ 779 \ 780 p += off; \ 781 return bpf_probe_read_kernel(p, 4, 0); \ 782 } \ 783 SEC("?" type) \ 784 __description(type ": reject helper read ctx with variable offset") \ 785 __failure __msg("variable ctx access var_off=") \ 786 int no_rewrite_##name##_helper_read_var(void *ctx) \ 787 { \ 788 __u64 off_var = bpf_get_prandom_u32(); \ 789 char *p = ctx; \ 790 \ 791 off_var &= 4; \ 792 p += off_var; \ 793 return bpf_strncmp(p, 4, ctx_strncmp_target); \ 794 } \ 795 SEC("?" type) \ 796 __description(type ": reject helper write ctx with variable offset") \ 797 __failure __msg("variable ctx access var_off=") \ 798 int no_rewrite_##name##_helper_write_var(void *ctx) \ 799 { \ 800 __u64 off_var = bpf_get_prandom_u32(); \ 801 char *p = ctx; \ 802 \ 803 off_var &= 4; \ 804 p += off_var; \ 805 return bpf_probe_read_kernel(p, 4, 0); \ 806 } \ 807 SEC("?" type) \ 808 __description(type ": reject helper read zero-sized ctx access") \ 809 __failure __msg("R4 type=ctx expected=fp") \ 810 int no_rewrite_##name##_helper_read_zero(void *ctx) \ 811 { \ 812 return bpf_snprintf(0, 0, ctx_snprintf_fmt, ctx, 0); \ 813 } \ 814 SEC("?" type) \ 815 __description(type ": reject helper write zero-sized ctx access") \ 816 __failure __msg("R1 type=ctx expected=fp") \ 817 int no_rewrite_##name##_helper_write_zero(void *ctx) \ 818 { \ 819 return bpf_probe_read_kernel(ctx, 0, 0); \ 820 } \ 821 SEC("?" type) \ 822 __description(type ": reject kfunc ctx at fixed offset") \ 823 __failure __msg("dereference of modified ctx ptr") \ 824 int no_rewrite_##name##_kfunc_fixed(void *ctx) \ 825 { \ 826 char *p = ctx; \ 827 \ 828 p += off; \ 829 bpf_kfunc_call_test_mem_len_pass1(p, 4); \ 830 return 0; \ 831 } \ 832 SEC("?" type) \ 833 __description(type ": reject kfunc ctx with variable offset") \ 834 __failure __msg("variable ctx access var_off=") \ 835 int no_rewrite_##name##_kfunc_var(void *ctx) \ 836 { \ 837 __u64 off_var = bpf_get_prandom_u32(); \ 838 char *p = ctx; \ 839 \ 840 off_var &= 4; \ 841 p += off_var; \ 842 bpf_kfunc_call_test_mem_len_pass1(p, 4); \ 843 return 0; \ 844 } \ 845 SEC("?" type) \ 846 __description(type ": reject kfunc zero-sized ctx access") \ 847 __failure __msg("R1 type=ctx expected=fp") \ 848 int no_rewrite_##name##_kfunc_zero(void *ctx) \ 849 { \ 850 bpf_kfunc_call_test_mem_len_pass1(ctx, 0); \ 851 return 0; \ 852 } 853 854no_rewrite_ctx_access("kprobe", kprobe, 8, u64); 855no_rewrite_ctx_access("tracepoint", tp, 8, u64); 856no_rewrite_ctx_access("raw_tp", raw_tp, 8, u64); 857no_rewrite_ctx_access("raw_tracepoint.w", raw_tp_w, 8, u64); 858no_rewrite_ctx_access("fentry/bpf_modify_return_test", fentry, 8, u64); 859no_rewrite_ctx_access("cgroup/dev", cgroup_dev, 4, u32); 860no_rewrite_ctx_access("netfilter", netfilter, offsetof(struct bpf_nf_ctx, skb), u64); 861 862char _license[] SEC("license") = "GPL";