1496 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/ref_tracking.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include "../../../include/linux/filter.h"7#include "bpf_misc.h"8 9#define BPF_SK_LOOKUP(func) \10 /* struct bpf_sock_tuple tuple = {} */ \11 "r2 = 0;" \12 "*(u32*)(r10 - 8) = r2;" \13 "*(u64*)(r10 - 16) = r2;" \14 "*(u64*)(r10 - 24) = r2;" \15 "*(u64*)(r10 - 32) = r2;" \16 "*(u64*)(r10 - 40) = r2;" \17 "*(u64*)(r10 - 48) = r2;" \18 /* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \19 "r2 = r10;" \20 "r2 += -48;" \21 "r3 = %[sizeof_bpf_sock_tuple];"\22 "r4 = 0;" \23 "r5 = 0;" \24 "call %[" #func "];"25 26struct bpf_key {} __attribute__((preserve_access_index));27 28extern void bpf_key_put(struct bpf_key *key) __ksym;29extern struct bpf_key *bpf_lookup_system_key(__u64 id) __ksym;30extern struct bpf_key *bpf_lookup_user_key(__u32 serial, __u64 flags) __ksym;31 32/* BTF FUNC records are not generated for kfuncs referenced33 * from inline assembly. These records are necessary for34 * libbpf to link the program. The function below is a hack35 * to ensure that BTF FUNC records are generated.36 */37void __kfunc_btf_root(void)38{39 bpf_key_put(0);40 bpf_lookup_system_key(0);41 bpf_lookup_user_key(0, 0);42}43 44#define MAX_ENTRIES 1145 46struct test_val {47 unsigned int index;48 int foo[MAX_ENTRIES];49};50 51struct {52 __uint(type, BPF_MAP_TYPE_ARRAY);53 __uint(max_entries, 1);54 __type(key, int);55 __type(value, struct test_val);56} map_array_48b SEC(".maps");57 58struct {59 __uint(type, BPF_MAP_TYPE_RINGBUF);60 __uint(max_entries, 4096);61} map_ringbuf SEC(".maps");62 63void dummy_prog_42_tc(void);64void dummy_prog_24_tc(void);65void dummy_prog_loop1_tc(void);66 67struct {68 __uint(type, BPF_MAP_TYPE_PROG_ARRAY);69 __uint(max_entries, 4);70 __uint(key_size, sizeof(int));71 __array(values, void (void));72} map_prog1_tc SEC(".maps") = {73 .values = {74 [0] = (void *)&dummy_prog_42_tc,75 [1] = (void *)&dummy_prog_loop1_tc,76 [2] = (void *)&dummy_prog_24_tc,77 },78};79 80SEC("tc")81__auxiliary82__naked void dummy_prog_42_tc(void)83{84 asm volatile ("r0 = 42; exit;");85}86 87SEC("tc")88__auxiliary89__naked void dummy_prog_24_tc(void)90{91 asm volatile ("r0 = 24; exit;");92}93 94SEC("tc")95__auxiliary96__naked void dummy_prog_loop1_tc(void)97{98 asm volatile (" \99 r3 = 1; \100 r2 = %[map_prog1_tc] ll; \101 call %[bpf_tail_call]; \102 r0 = 41; \103 exit; \104" :105 : __imm(bpf_tail_call),106 __imm_addr(map_prog1_tc)107 : __clobber_all);108}109 110SEC("tc")111__description("reference tracking: leak potential reference")112__failure __msg("Unreleased reference")113__naked void reference_tracking_leak_potential_reference(void)114{115 asm volatile (116 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)117" r6 = r0; /* leak reference */ \118 exit; \119" :120 : __imm(bpf_sk_lookup_tcp),121 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))122 : __clobber_all);123}124 125SEC("tc")126__description("reference tracking: leak potential reference to sock_common")127__failure __msg("Unreleased reference")128__naked void potential_reference_to_sock_common_1(void)129{130 asm volatile (131 BPF_SK_LOOKUP(bpf_skc_lookup_tcp)132" r6 = r0; /* leak reference */ \133 exit; \134" :135 : __imm(bpf_skc_lookup_tcp),136 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))137 : __clobber_all);138}139 140SEC("tc")141__description("reference tracking: leak potential reference on stack")142__failure __msg("Unreleased reference")143__naked void leak_potential_reference_on_stack(void)144{145 asm volatile (146 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)147" r4 = r10; \148 r4 += -8; \149 *(u64*)(r4 + 0) = r0; \150 r0 = 0; \151 exit; \152" :153 : __imm(bpf_sk_lookup_tcp),154 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))155 : __clobber_all);156}157 158SEC("tc")159__description("reference tracking: leak potential reference on stack 2")160__failure __msg("Unreleased reference")161__naked void potential_reference_on_stack_2(void)162{163 asm volatile (164 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)165" r4 = r10; \166 r4 += -8; \167 *(u64*)(r4 + 0) = r0; \168 r0 = 0; \169 r1 = 0; \170 *(u64*)(r4 + 0) = r1; \171 exit; \172" :173 : __imm(bpf_sk_lookup_tcp),174 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))175 : __clobber_all);176}177 178SEC("tc")179__description("reference tracking: zero potential reference")180__failure __msg("Unreleased reference")181__naked void reference_tracking_zero_potential_reference(void)182{183 asm volatile (184 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)185" r0 = 0; /* leak reference */ \186 exit; \187" :188 : __imm(bpf_sk_lookup_tcp),189 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))190 : __clobber_all);191}192 193SEC("tc")194__description("reference tracking: zero potential reference to sock_common")195__failure __msg("Unreleased reference")196__naked void potential_reference_to_sock_common_2(void)197{198 asm volatile (199 BPF_SK_LOOKUP(bpf_skc_lookup_tcp)200" r0 = 0; /* leak reference */ \201 exit; \202" :203 : __imm(bpf_skc_lookup_tcp),204 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))205 : __clobber_all);206}207 208SEC("tc")209__description("reference tracking: copy and zero potential references")210__failure __msg("Unreleased reference")211__naked void copy_and_zero_potential_references(void)212{213 asm volatile (214 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)215" r7 = r0; \216 r0 = 0; \217 r7 = 0; /* leak reference */ \218 exit; \219" :220 : __imm(bpf_sk_lookup_tcp),221 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))222 : __clobber_all);223}224 225SEC("lsm.s/bpf")226__description("reference tracking: acquire/release user key reference")227__success228__naked void acquire_release_user_key_reference(void)229{230 asm volatile (" \231 r1 = -3; \232 r2 = 0; \233 call %[bpf_lookup_user_key]; \234 if r0 == 0 goto l0_%=; \235 r1 = r0; \236 call %[bpf_key_put]; \237l0_%=: r0 = 0; \238 exit; \239" :240 : __imm(bpf_key_put),241 __imm(bpf_lookup_user_key)242 : __clobber_all);243}244 245SEC("lsm.s/bpf")246__description("reference tracking: acquire/release system key reference")247__success248__naked void acquire_release_system_key_reference(void)249{250 asm volatile (" \251 r1 = 1; \252 call %[bpf_lookup_system_key]; \253 if r0 == 0 goto l0_%=; \254 r1 = r0; \255 call %[bpf_key_put]; \256l0_%=: r0 = 0; \257 exit; \258" :259 : __imm(bpf_key_put),260 __imm(bpf_lookup_system_key)261 : __clobber_all);262}263 264SEC("lsm.s/bpf")265__description("reference tracking: release user key reference without check")266__failure __msg("Possibly NULL pointer passed to trusted arg0")267__naked void user_key_reference_without_check(void)268{269 asm volatile (" \270 r1 = -3; \271 r2 = 0; \272 call %[bpf_lookup_user_key]; \273 r1 = r0; \274 call %[bpf_key_put]; \275 r0 = 0; \276 exit; \277" :278 : __imm(bpf_key_put),279 __imm(bpf_lookup_user_key)280 : __clobber_all);281}282 283SEC("lsm.s/bpf")284__description("reference tracking: release system key reference without check")285__failure __msg("Possibly NULL pointer passed to trusted arg0")286__naked void system_key_reference_without_check(void)287{288 asm volatile (" \289 r1 = 1; \290 call %[bpf_lookup_system_key]; \291 r1 = r0; \292 call %[bpf_key_put]; \293 r0 = 0; \294 exit; \295" :296 : __imm(bpf_key_put),297 __imm(bpf_lookup_system_key)298 : __clobber_all);299}300 301SEC("lsm.s/bpf")302__description("reference tracking: release with NULL key pointer")303__failure __msg("Possibly NULL pointer passed to trusted arg0")304__naked void release_with_null_key_pointer(void)305{306 asm volatile (" \307 r1 = 0; \308 call %[bpf_key_put]; \309 r0 = 0; \310 exit; \311" :312 : __imm(bpf_key_put)313 : __clobber_all);314}315 316SEC("lsm.s/bpf")317__description("reference tracking: leak potential reference to user key")318__failure __msg("Unreleased reference")319__naked void potential_reference_to_user_key(void)320{321 asm volatile (" \322 r1 = -3; \323 r2 = 0; \324 call %[bpf_lookup_user_key]; \325 exit; \326" :327 : __imm(bpf_lookup_user_key)328 : __clobber_all);329}330 331SEC("lsm.s/bpf")332__description("reference tracking: leak potential reference to system key")333__failure __msg("Unreleased reference")334__naked void potential_reference_to_system_key(void)335{336 asm volatile (" \337 r1 = 1; \338 call %[bpf_lookup_system_key]; \339 exit; \340" :341 : __imm(bpf_lookup_system_key)342 : __clobber_all);343}344 345SEC("tc")346__description("reference tracking: release reference without check")347__failure __msg("type=sock_or_null expected=sock")348__naked void tracking_release_reference_without_check(void)349{350 asm volatile (351 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)352" /* reference in r0 may be NULL */ \353 r1 = r0; \354 r2 = 0; \355 call %[bpf_sk_release]; \356 exit; \357" :358 : __imm(bpf_sk_lookup_tcp),359 __imm(bpf_sk_release),360 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))361 : __clobber_all);362}363 364SEC("tc")365__description("reference tracking: release reference to sock_common without check")366__failure __msg("type=sock_common_or_null expected=sock")367__naked void to_sock_common_without_check(void)368{369 asm volatile (370 BPF_SK_LOOKUP(bpf_skc_lookup_tcp)371" /* reference in r0 may be NULL */ \372 r1 = r0; \373 r2 = 0; \374 call %[bpf_sk_release]; \375 exit; \376" :377 : __imm(bpf_sk_release),378 __imm(bpf_skc_lookup_tcp),379 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))380 : __clobber_all);381}382 383SEC("tc")384__description("reference tracking: release reference")385__success __retval(0)386__naked void reference_tracking_release_reference(void)387{388 asm volatile (389 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)390" r1 = r0; \391 if r0 == 0 goto l0_%=; \392 call %[bpf_sk_release]; \393l0_%=: exit; \394" :395 : __imm(bpf_sk_lookup_tcp),396 __imm(bpf_sk_release),397 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))398 : __clobber_all);399}400 401SEC("tc")402__description("reference tracking: release reference to sock_common")403__success __retval(0)404__naked void release_reference_to_sock_common(void)405{406 asm volatile (407 BPF_SK_LOOKUP(bpf_skc_lookup_tcp)408" r1 = r0; \409 if r0 == 0 goto l0_%=; \410 call %[bpf_sk_release]; \411l0_%=: exit; \412" :413 : __imm(bpf_sk_release),414 __imm(bpf_skc_lookup_tcp),415 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))416 : __clobber_all);417}418 419SEC("tc")420__description("reference tracking: release reference 2")421__success __retval(0)422__naked void reference_tracking_release_reference_2(void)423{424 asm volatile (425 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)426" r1 = r0; \427 if r0 != 0 goto l0_%=; \428 exit; \429l0_%=: call %[bpf_sk_release]; \430 exit; \431" :432 : __imm(bpf_sk_lookup_tcp),433 __imm(bpf_sk_release),434 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))435 : __clobber_all);436}437 438SEC("tc")439__description("reference tracking: release reference twice")440__failure __msg("type=scalar expected=sock")441__naked void reference_tracking_release_reference_twice(void)442{443 asm volatile (444 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)445" r1 = r0; \446 r6 = r0; \447 if r0 == 0 goto l0_%=; \448 call %[bpf_sk_release]; \449l0_%=: r1 = r6; \450 call %[bpf_sk_release]; \451 exit; \452" :453 : __imm(bpf_sk_lookup_tcp),454 __imm(bpf_sk_release),455 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))456 : __clobber_all);457}458 459SEC("tc")460__description("reference tracking: release reference twice inside branch")461__failure __msg("type=scalar expected=sock")462__naked void release_reference_twice_inside_branch(void)463{464 asm volatile (465 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)466" r1 = r0; \467 r6 = r0; \468 if r0 == 0 goto l0_%=; /* goto end */ \469 call %[bpf_sk_release]; \470 r1 = r6; \471 call %[bpf_sk_release]; \472l0_%=: exit; \473" :474 : __imm(bpf_sk_lookup_tcp),475 __imm(bpf_sk_release),476 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))477 : __clobber_all);478}479 480SEC("tc")481__description("reference tracking: alloc, check, free in one subbranch")482__failure __msg("Unreleased reference")483__flag(BPF_F_ANY_ALIGNMENT)484__naked void check_free_in_one_subbranch(void)485{486 asm volatile (" \487 r2 = *(u32*)(r1 + %[__sk_buff_data]); \488 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \489 r0 = r2; \490 r0 += 16; \491 /* if (offsetof(skb, mark) > data_len) exit; */ \492 if r0 <= r3 goto l0_%=; \493 exit; \494l0_%=: r6 = *(u32*)(r2 + %[__sk_buff_mark]); \495" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)496" if r6 == 0 goto l1_%=; /* mark == 0? */\497 /* Leak reference in R0 */ \498 exit; \499l1_%=: if r0 == 0 goto l2_%=; /* sk NULL? */ \500 r1 = r0; \501 call %[bpf_sk_release]; \502l2_%=: exit; \503" :504 : __imm(bpf_sk_lookup_tcp),505 __imm(bpf_sk_release),506 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),507 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),508 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),509 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))510 : __clobber_all);511}512 513SEC("tc")514__description("reference tracking: alloc, check, free in both subbranches")515__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)516__naked void check_free_in_both_subbranches(void)517{518 asm volatile (" \519 r2 = *(u32*)(r1 + %[__sk_buff_data]); \520 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \521 r0 = r2; \522 r0 += 16; \523 /* if (offsetof(skb, mark) > data_len) exit; */ \524 if r0 <= r3 goto l0_%=; \525 exit; \526l0_%=: r6 = *(u32*)(r2 + %[__sk_buff_mark]); \527" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)528" if r6 == 0 goto l1_%=; /* mark == 0? */\529 if r0 == 0 goto l2_%=; /* sk NULL? */ \530 r1 = r0; \531 call %[bpf_sk_release]; \532l2_%=: exit; \533l1_%=: if r0 == 0 goto l3_%=; /* sk NULL? */ \534 r1 = r0; \535 call %[bpf_sk_release]; \536l3_%=: exit; \537" :538 : __imm(bpf_sk_lookup_tcp),539 __imm(bpf_sk_release),540 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),541 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),542 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),543 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))544 : __clobber_all);545}546 547SEC("tc")548__description("reference tracking in call: free reference in subprog")549__success __retval(0)550__naked void call_free_reference_in_subprog(void)551{552 asm volatile (553 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)554" r1 = r0; /* unchecked reference */ \555 call call_free_reference_in_subprog__1; \556 r0 = 0; \557 exit; \558" :559 : __imm(bpf_sk_lookup_tcp),560 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))561 : __clobber_all);562}563 564static __naked __noinline __attribute__((used))565void call_free_reference_in_subprog__1(void)566{567 asm volatile (" \568 /* subprog 1 */ \569 r2 = r1; \570 if r2 == 0 goto l0_%=; \571 call %[bpf_sk_release]; \572l0_%=: exit; \573" :574 : __imm(bpf_sk_release)575 : __clobber_all);576}577 578SEC("tc")579__description("reference tracking in call: free reference in subprog and outside")580__failure __msg("type=scalar expected=sock")581__naked void reference_in_subprog_and_outside(void)582{583 asm volatile (584 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)585" r1 = r0; /* unchecked reference */ \586 r6 = r0; \587 call reference_in_subprog_and_outside__1; \588 r1 = r6; \589 call %[bpf_sk_release]; \590 exit; \591" :592 : __imm(bpf_sk_lookup_tcp),593 __imm(bpf_sk_release),594 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))595 : __clobber_all);596}597 598static __naked __noinline __attribute__((used))599void reference_in_subprog_and_outside__1(void)600{601 asm volatile (" \602 /* subprog 1 */ \603 r2 = r1; \604 if r2 == 0 goto l0_%=; \605 call %[bpf_sk_release]; \606l0_%=: exit; \607" :608 : __imm(bpf_sk_release)609 : __clobber_all);610}611 612SEC("tc")613__description("reference tracking in call: alloc & leak reference in subprog")614__failure __msg("Unreleased reference")615__naked void alloc_leak_reference_in_subprog(void)616{617 asm volatile (" \618 r4 = r10; \619 r4 += -8; \620 call alloc_leak_reference_in_subprog__1; \621 r1 = r0; \622 r0 = 0; \623 exit; \624" ::: __clobber_all);625}626 627static __naked __noinline __attribute__((used))628void alloc_leak_reference_in_subprog__1(void)629{630 asm volatile (" \631 /* subprog 1 */ \632 r6 = r4; \633" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)634" /* spill unchecked sk_ptr into stack of caller */\635 *(u64*)(r6 + 0) = r0; \636 r1 = r0; \637 exit; \638" :639 : __imm(bpf_sk_lookup_tcp),640 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))641 : __clobber_all);642}643 644SEC("tc")645__description("reference tracking in call: alloc in subprog, release outside")646__success __retval(POINTER_VALUE)647__naked void alloc_in_subprog_release_outside(void)648{649 asm volatile (" \650 r4 = r10; \651 call alloc_in_subprog_release_outside__1; \652 r1 = r0; \653 if r0 == 0 goto l0_%=; \654 call %[bpf_sk_release]; \655l0_%=: exit; \656" :657 : __imm(bpf_sk_release)658 : __clobber_all);659}660 661static __naked __noinline __attribute__((used))662void alloc_in_subprog_release_outside__1(void)663{664 asm volatile (" \665 /* subprog 1 */ \666" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)667" exit; /* return sk */ \668" :669 : __imm(bpf_sk_lookup_tcp),670 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))671 : __clobber_all);672}673 674SEC("tc")675__description("reference tracking in call: sk_ptr leak into caller stack")676__failure __msg("Unreleased reference")677__naked void ptr_leak_into_caller_stack(void)678{679 asm volatile (" \680 r4 = r10; \681 r4 += -8; \682 call ptr_leak_into_caller_stack__1; \683 r0 = 0; \684 exit; \685" ::: __clobber_all);686}687 688static __naked __noinline __attribute__((used))689void ptr_leak_into_caller_stack__1(void)690{691 asm volatile (" \692 /* subprog 1 */ \693 r5 = r10; \694 r5 += -8; \695 *(u64*)(r5 + 0) = r4; \696 call ptr_leak_into_caller_stack__2; \697 /* spill unchecked sk_ptr into stack of caller */\698 r5 = r10; \699 r5 += -8; \700 r4 = *(u64*)(r5 + 0); \701 *(u64*)(r4 + 0) = r0; \702 exit; \703" ::: __clobber_all);704}705 706static __naked __noinline __attribute__((used))707void ptr_leak_into_caller_stack__2(void)708{709 asm volatile (" \710 /* subprog 2 */ \711" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)712" exit; \713" :714 : __imm(bpf_sk_lookup_tcp),715 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))716 : __clobber_all);717}718 719SEC("tc")720__description("reference tracking in call: sk_ptr spill into caller stack")721__success __retval(0)722__naked void ptr_spill_into_caller_stack(void)723{724 asm volatile (" \725 r4 = r10; \726 r4 += -8; \727 call ptr_spill_into_caller_stack__1; \728 r0 = 0; \729 exit; \730" ::: __clobber_all);731}732 733static __naked __noinline __attribute__((used))734void ptr_spill_into_caller_stack__1(void)735{736 asm volatile (" \737 /* subprog 1 */ \738 r5 = r10; \739 r5 += -8; \740 *(u64*)(r5 + 0) = r4; \741 call ptr_spill_into_caller_stack__2; \742 /* spill unchecked sk_ptr into stack of caller */\743 r5 = r10; \744 r5 += -8; \745 r4 = *(u64*)(r5 + 0); \746 *(u64*)(r4 + 0) = r0; \747 if r0 == 0 goto l0_%=; \748 /* now the sk_ptr is verified, free the reference */\749 r1 = *(u64*)(r4 + 0); \750 call %[bpf_sk_release]; \751l0_%=: exit; \752" :753 : __imm(bpf_sk_release)754 : __clobber_all);755}756 757static __naked __noinline __attribute__((used))758void ptr_spill_into_caller_stack__2(void)759{760 asm volatile (" \761 /* subprog 2 */ \762" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)763" exit; \764" :765 : __imm(bpf_sk_lookup_tcp),766 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))767 : __clobber_all);768}769 770SEC("tc")771__description("reference tracking: allow LD_ABS")772__success __retval(0)773__naked void reference_tracking_allow_ld_abs(void)774{775 asm volatile (" \776 r6 = r1; \777" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)778" r1 = r0; \779 if r0 == 0 goto l0_%=; \780 call %[bpf_sk_release]; \781l0_%=: r0 = *(u8*)skb[0]; \782 r0 = *(u16*)skb[0]; \783 r0 = *(u32*)skb[0]; \784 exit; \785" :786 : __imm(bpf_sk_lookup_tcp),787 __imm(bpf_sk_release),788 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))789 : __clobber_all);790}791 792SEC("tc")793__description("reference tracking: forbid LD_ABS while holding reference")794__failure __msg("BPF_LD_[ABS|IND] cannot be mixed with socket references")795__naked void ld_abs_while_holding_reference(void)796{797 asm volatile (" \798 r6 = r1; \799" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)800" r0 = *(u8*)skb[0]; \801 r0 = *(u16*)skb[0]; \802 r0 = *(u32*)skb[0]; \803 r1 = r0; \804 if r0 == 0 goto l0_%=; \805 call %[bpf_sk_release]; \806l0_%=: exit; \807" :808 : __imm(bpf_sk_lookup_tcp),809 __imm(bpf_sk_release),810 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))811 : __clobber_all);812}813 814SEC("tc")815__description("reference tracking: allow LD_IND")816__success __retval(1)817__naked void reference_tracking_allow_ld_ind(void)818{819 asm volatile (" \820 r6 = r1; \821" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)822" r1 = r0; \823 if r0 == 0 goto l0_%=; \824 call %[bpf_sk_release]; \825l0_%=: r7 = 1; \826 .8byte %[ld_ind]; \827 r0 = r7; \828 exit; \829" :830 : __imm(bpf_sk_lookup_tcp),831 __imm(bpf_sk_release),832 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)),833 __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000))834 : __clobber_all);835}836 837SEC("tc")838__description("reference tracking: forbid LD_IND while holding reference")839__failure __msg("BPF_LD_[ABS|IND] cannot be mixed with socket references")840__naked void ld_ind_while_holding_reference(void)841{842 asm volatile (" \843 r6 = r1; \844" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)845" r4 = r0; \846 r7 = 1; \847 .8byte %[ld_ind]; \848 r0 = r7; \849 r1 = r4; \850 if r1 == 0 goto l0_%=; \851 call %[bpf_sk_release]; \852l0_%=: exit; \853" :854 : __imm(bpf_sk_lookup_tcp),855 __imm(bpf_sk_release),856 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)),857 __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000))858 : __clobber_all);859}860 861SEC("tc")862__description("reference tracking: check reference or tail call")863__success __retval(0)864__naked void check_reference_or_tail_call(void)865{866 asm volatile (" \867 r7 = r1; \868" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)869" /* if (sk) bpf_sk_release() */ \870 r1 = r0; \871 if r1 != 0 goto l0_%=; \872 /* bpf_tail_call() */ \873 r3 = 3; \874 r2 = %[map_prog1_tc] ll; \875 r1 = r7; \876 call %[bpf_tail_call]; \877 r0 = 0; \878 exit; \879l0_%=: call %[bpf_sk_release]; \880 exit; \881" :882 : __imm(bpf_sk_lookup_tcp),883 __imm(bpf_sk_release),884 __imm(bpf_tail_call),885 __imm_addr(map_prog1_tc),886 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))887 : __clobber_all);888}889 890SEC("tc")891__description("reference tracking: release reference then tail call")892__success __retval(0)893__naked void release_reference_then_tail_call(void)894{895 asm volatile (" \896 r7 = r1; \897" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)898" /* if (sk) bpf_sk_release() */ \899 r1 = r0; \900 if r1 == 0 goto l0_%=; \901 call %[bpf_sk_release]; \902l0_%=: /* bpf_tail_call() */ \903 r3 = 3; \904 r2 = %[map_prog1_tc] ll; \905 r1 = r7; \906 call %[bpf_tail_call]; \907 r0 = 0; \908 exit; \909" :910 : __imm(bpf_sk_lookup_tcp),911 __imm(bpf_sk_release),912 __imm(bpf_tail_call),913 __imm_addr(map_prog1_tc),914 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))915 : __clobber_all);916}917 918SEC("tc")919__description("reference tracking: leak possible reference over tail call")920__failure __msg("tail_call would lead to reference leak")921__naked void possible_reference_over_tail_call(void)922{923 asm volatile (" \924 r7 = r1; \925 /* Look up socket and store in REG_6 */ \926" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)927" /* bpf_tail_call() */ \928 r6 = r0; \929 r3 = 3; \930 r2 = %[map_prog1_tc] ll; \931 r1 = r7; \932 call %[bpf_tail_call]; \933 r0 = 0; \934 /* if (sk) bpf_sk_release() */ \935 r1 = r6; \936 if r1 == 0 goto l0_%=; \937 call %[bpf_sk_release]; \938l0_%=: exit; \939" :940 : __imm(bpf_sk_lookup_tcp),941 __imm(bpf_sk_release),942 __imm(bpf_tail_call),943 __imm_addr(map_prog1_tc),944 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))945 : __clobber_all);946}947 948SEC("tc")949__description("reference tracking: leak checked reference over tail call")950__failure __msg("tail_call would lead to reference leak")951__naked void checked_reference_over_tail_call(void)952{953 asm volatile (" \954 r7 = r1; \955 /* Look up socket and store in REG_6 */ \956" BPF_SK_LOOKUP(bpf_sk_lookup_tcp)957" r6 = r0; \958 /* if (!sk) goto end */ \959 if r0 == 0 goto l0_%=; \960 /* bpf_tail_call() */ \961 r3 = 0; \962 r2 = %[map_prog1_tc] ll; \963 r1 = r7; \964 call %[bpf_tail_call]; \965 r0 = 0; \966 r1 = r6; \967l0_%=: call %[bpf_sk_release]; \968 exit; \969" :970 : __imm(bpf_sk_lookup_tcp),971 __imm(bpf_sk_release),972 __imm(bpf_tail_call),973 __imm_addr(map_prog1_tc),974 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))975 : __clobber_all);976}977 978SEC("tc")979__description("reference tracking: mangle and release sock_or_null")980__failure __msg("R1 pointer arithmetic on sock_or_null prohibited")981__naked void and_release_sock_or_null(void)982{983 asm volatile (984 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)985" r1 = r0; \986 r1 += 5; \987 if r0 == 0 goto l0_%=; \988 call %[bpf_sk_release]; \989l0_%=: exit; \990" :991 : __imm(bpf_sk_lookup_tcp),992 __imm(bpf_sk_release),993 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))994 : __clobber_all);995}996 997SEC("tc")998__description("reference tracking: mangle and release sock")999__failure __msg("R1 pointer arithmetic on sock prohibited")1000__naked void tracking_mangle_and_release_sock(void)1001{1002 asm volatile (1003 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1004" r1 = r0; \1005 if r0 == 0 goto l0_%=; \1006 r1 += 5; \1007 call %[bpf_sk_release]; \1008l0_%=: exit; \1009" :1010 : __imm(bpf_sk_lookup_tcp),1011 __imm(bpf_sk_release),1012 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1013 : __clobber_all);1014}1015 1016SEC("tc")1017__description("reference tracking: access member")1018__success __retval(0)1019__naked void reference_tracking_access_member(void)1020{1021 asm volatile (1022 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1023" r6 = r0; \1024 if r0 == 0 goto l0_%=; \1025 r2 = *(u32*)(r0 + 4); \1026 r1 = r6; \1027 call %[bpf_sk_release]; \1028l0_%=: exit; \1029" :1030 : __imm(bpf_sk_lookup_tcp),1031 __imm(bpf_sk_release),1032 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1033 : __clobber_all);1034}1035 1036SEC("tc")1037__description("reference tracking: write to member")1038__failure __msg("cannot write into sock")1039__naked void reference_tracking_write_to_member(void)1040{1041 asm volatile (1042 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1043" r6 = r0; \1044 if r0 == 0 goto l0_%=; \1045 r1 = r6; \1046 r2 = 42 ll; \1047 *(u32*)(r1 + %[bpf_sock_mark]) = r2; \1048 r1 = r6; \1049l0_%=: call %[bpf_sk_release]; \1050 r0 = 0 ll; \1051 exit; \1052" :1053 : __imm(bpf_sk_lookup_tcp),1054 __imm(bpf_sk_release),1055 __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)),1056 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1057 : __clobber_all);1058}1059 1060SEC("tc")1061__description("reference tracking: invalid 64-bit access of member")1062__failure __msg("invalid sock access off=0 size=8")1063__naked void _64_bit_access_of_member(void)1064{1065 asm volatile (1066 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1067" r6 = r0; \1068 if r0 == 0 goto l0_%=; \1069 r2 = *(u64*)(r0 + 0); \1070 r1 = r6; \1071 call %[bpf_sk_release]; \1072l0_%=: exit; \1073" :1074 : __imm(bpf_sk_lookup_tcp),1075 __imm(bpf_sk_release),1076 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1077 : __clobber_all);1078}1079 1080SEC("tc")1081__description("reference tracking: access after release")1082__failure __msg("!read_ok")1083__naked void reference_tracking_access_after_release(void)1084{1085 asm volatile (1086 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1087" r1 = r0; \1088 if r0 == 0 goto l0_%=; \1089 call %[bpf_sk_release]; \1090 r2 = *(u32*)(r1 + 0); \1091l0_%=: exit; \1092" :1093 : __imm(bpf_sk_lookup_tcp),1094 __imm(bpf_sk_release),1095 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1096 : __clobber_all);1097}1098 1099SEC("tc")1100__description("reference tracking: direct access for lookup")1101__success __retval(0)1102__naked void tracking_direct_access_for_lookup(void)1103{1104 asm volatile (" \1105 /* Check that the packet is at least 64B long */\1106 r2 = *(u32*)(r1 + %[__sk_buff_data]); \1107 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \1108 r0 = r2; \1109 r0 += 64; \1110 if r0 > r3 goto l0_%=; \1111 /* sk = sk_lookup_tcp(ctx, skb->data, ...) */ \1112 r3 = %[sizeof_bpf_sock_tuple]; \1113 r4 = 0; \1114 r5 = 0; \1115 call %[bpf_sk_lookup_tcp]; \1116 r6 = r0; \1117 if r0 == 0 goto l0_%=; \1118 r2 = *(u32*)(r0 + 4); \1119 r1 = r6; \1120 call %[bpf_sk_release]; \1121l0_%=: exit; \1122" :1123 : __imm(bpf_sk_lookup_tcp),1124 __imm(bpf_sk_release),1125 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),1126 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),1127 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1128 : __clobber_all);1129}1130 1131SEC("tc")1132__description("reference tracking: use ptr from bpf_tcp_sock() after release")1133__failure __msg("invalid mem access")1134__flag(BPF_F_ANY_ALIGNMENT)1135__naked void bpf_tcp_sock_after_release(void)1136{1137 asm volatile (1138 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1139" if r0 != 0 goto l0_%=; \1140 exit; \1141l0_%=: r6 = r0; \1142 r1 = r0; \1143 call %[bpf_tcp_sock]; \1144 if r0 != 0 goto l1_%=; \1145 r1 = r6; \1146 call %[bpf_sk_release]; \1147 exit; \1148l1_%=: r7 = r0; \1149 r1 = r6; \1150 call %[bpf_sk_release]; \1151 r0 = *(u32*)(r7 + %[bpf_tcp_sock_snd_cwnd]); \1152 exit; \1153" :1154 : __imm(bpf_sk_lookup_tcp),1155 __imm(bpf_sk_release),1156 __imm(bpf_tcp_sock),1157 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)),1158 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1159 : __clobber_all);1160}1161 1162SEC("tc")1163__description("reference tracking: use ptr from bpf_sk_fullsock() after release")1164__failure __msg("invalid mem access")1165__flag(BPF_F_ANY_ALIGNMENT)1166__naked void bpf_sk_fullsock_after_release(void)1167{1168 asm volatile (1169 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1170" if r0 != 0 goto l0_%=; \1171 exit; \1172l0_%=: r6 = r0; \1173 r1 = r0; \1174 call %[bpf_sk_fullsock]; \1175 if r0 != 0 goto l1_%=; \1176 r1 = r6; \1177 call %[bpf_sk_release]; \1178 exit; \1179l1_%=: r7 = r0; \1180 r1 = r6; \1181 call %[bpf_sk_release]; \1182 r0 = *(u32*)(r7 + %[bpf_sock_type]); \1183 exit; \1184" :1185 : __imm(bpf_sk_fullsock),1186 __imm(bpf_sk_lookup_tcp),1187 __imm(bpf_sk_release),1188 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1189 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1190 : __clobber_all);1191}1192 1193SEC("tc")1194__description("reference tracking: use ptr from bpf_sk_fullsock(tp) after release")1195__failure __msg("invalid mem access")1196__flag(BPF_F_ANY_ALIGNMENT)1197__naked void sk_fullsock_tp_after_release(void)1198{1199 asm volatile (1200 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1201" if r0 != 0 goto l0_%=; \1202 exit; \1203l0_%=: r6 = r0; \1204 r1 = r0; \1205 call %[bpf_tcp_sock]; \1206 if r0 != 0 goto l1_%=; \1207 r1 = r6; \1208 call %[bpf_sk_release]; \1209 exit; \1210l1_%=: r1 = r0; \1211 call %[bpf_sk_fullsock]; \1212 r1 = r6; \1213 r6 = r0; \1214 call %[bpf_sk_release]; \1215 if r6 != 0 goto l2_%=; \1216 exit; \1217l2_%=: r0 = *(u32*)(r6 + %[bpf_sock_type]); \1218 exit; \1219" :1220 : __imm(bpf_sk_fullsock),1221 __imm(bpf_sk_lookup_tcp),1222 __imm(bpf_sk_release),1223 __imm(bpf_tcp_sock),1224 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1225 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1226 : __clobber_all);1227}1228 1229SEC("tc")1230__description("reference tracking: use sk after bpf_sk_release(tp)")1231__failure __msg("invalid mem access")1232__flag(BPF_F_ANY_ALIGNMENT)1233__naked void after_bpf_sk_release_tp(void)1234{1235 asm volatile (1236 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1237" if r0 != 0 goto l0_%=; \1238 exit; \1239l0_%=: r6 = r0; \1240 r1 = r0; \1241 call %[bpf_tcp_sock]; \1242 if r0 != 0 goto l1_%=; \1243 r1 = r6; \1244 call %[bpf_sk_release]; \1245 exit; \1246l1_%=: r1 = r0; \1247 call %[bpf_sk_release]; \1248 r0 = *(u32*)(r6 + %[bpf_sock_type]); \1249 exit; \1250" :1251 : __imm(bpf_sk_lookup_tcp),1252 __imm(bpf_sk_release),1253 __imm(bpf_tcp_sock),1254 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1255 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1256 : __clobber_all);1257}1258 1259SEC("tc")1260__description("reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)")1261__success __retval(0)1262__naked void after_bpf_sk_release_sk(void)1263{1264 asm volatile (1265 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1266" if r0 != 0 goto l0_%=; \1267 exit; \1268l0_%=: r6 = r0; \1269 r1 = r0; \1270 call %[bpf_get_listener_sock]; \1271 if r0 != 0 goto l1_%=; \1272 r1 = r6; \1273 call %[bpf_sk_release]; \1274 exit; \1275l1_%=: r1 = r6; \1276 r6 = r0; \1277 call %[bpf_sk_release]; \1278 r0 = *(u32*)(r6 + %[bpf_sock_src_port]); \1279 exit; \1280" :1281 : __imm(bpf_get_listener_sock),1282 __imm(bpf_sk_lookup_tcp),1283 __imm(bpf_sk_release),1284 __imm_const(bpf_sock_src_port, offsetof(struct bpf_sock, src_port)),1285 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1286 : __clobber_all);1287}1288 1289SEC("tc")1290__description("reference tracking: bpf_sk_release(listen_sk)")1291__failure __msg("R1 must be referenced when passed to release function")1292__naked void bpf_sk_release_listen_sk(void)1293{1294 asm volatile (1295 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1296" if r0 != 0 goto l0_%=; \1297 exit; \1298l0_%=: r6 = r0; \1299 r1 = r0; \1300 call %[bpf_get_listener_sock]; \1301 if r0 != 0 goto l1_%=; \1302 r1 = r6; \1303 call %[bpf_sk_release]; \1304 exit; \1305l1_%=: r1 = r0; \1306 call %[bpf_sk_release]; \1307 r0 = *(u32*)(r6 + %[bpf_sock_type]); \1308 r1 = r6; \1309 call %[bpf_sk_release]; \1310 exit; \1311" :1312 : __imm(bpf_get_listener_sock),1313 __imm(bpf_sk_lookup_tcp),1314 __imm(bpf_sk_release),1315 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)),1316 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1317 : __clobber_all);1318}1319 1320/* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */1321SEC("tc")1322__description("reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)")1323__failure __msg("invalid mem access")1324__naked void and_bpf_tcp_sock_sk(void)1325{1326 asm volatile (1327 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1328" if r0 != 0 goto l0_%=; \1329 exit; \1330l0_%=: r6 = r0; \1331 r1 = r0; \1332 call %[bpf_sk_fullsock]; \1333 r7 = r0; \1334 r1 = r6; \1335 call %[bpf_tcp_sock]; \1336 r8 = r0; \1337 if r7 != 0 goto l1_%=; \1338 r1 = r6; \1339 call %[bpf_sk_release]; \1340 exit; \1341l1_%=: r0 = *(u32*)(r8 + %[bpf_tcp_sock_snd_cwnd]); \1342 r1 = r6; \1343 call %[bpf_sk_release]; \1344 exit; \1345" :1346 : __imm(bpf_sk_fullsock),1347 __imm(bpf_sk_lookup_tcp),1348 __imm(bpf_sk_release),1349 __imm(bpf_tcp_sock),1350 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)),1351 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1352 : __clobber_all);1353}1354 1355SEC("tc")1356__description("reference tracking: branch tracking valid pointer null comparison")1357__success __retval(0)1358__naked void tracking_valid_pointer_null_comparison(void)1359{1360 asm volatile (1361 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1362" r6 = r0; \1363 r3 = 1; \1364 if r6 != 0 goto l0_%=; \1365 r3 = 0; \1366l0_%=: if r6 == 0 goto l1_%=; \1367 r1 = r6; \1368 call %[bpf_sk_release]; \1369l1_%=: exit; \1370" :1371 : __imm(bpf_sk_lookup_tcp),1372 __imm(bpf_sk_release),1373 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1374 : __clobber_all);1375}1376 1377SEC("tc")1378__description("reference tracking: branch tracking valid pointer value comparison")1379__failure __msg("Unreleased reference")1380__naked void tracking_valid_pointer_value_comparison(void)1381{1382 asm volatile (1383 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1384" r6 = r0; \1385 r3 = 1; \1386 if r6 == 0 goto l0_%=; \1387 r3 = 0; \1388 if r6 == 1234 goto l0_%=; \1389 r1 = r6; \1390 call %[bpf_sk_release]; \1391l0_%=: exit; \1392" :1393 : __imm(bpf_sk_lookup_tcp),1394 __imm(bpf_sk_release),1395 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1396 : __clobber_all);1397}1398 1399SEC("tc")1400__description("reference tracking: bpf_sk_release(btf_tcp_sock)")1401__success1402__retval(0)1403__naked void sk_release_btf_tcp_sock(void)1404{1405 asm volatile (1406 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1407" if r0 != 0 goto l0_%=; \1408 exit; \1409l0_%=: r6 = r0; \1410 r1 = r0; \1411 call %[bpf_skc_to_tcp_sock]; \1412 if r0 != 0 goto l1_%=; \1413 r1 = r6; \1414 call %[bpf_sk_release]; \1415 exit; \1416l1_%=: r1 = r0; \1417 call %[bpf_sk_release]; \1418 exit; \1419" :1420 : __imm(bpf_sk_lookup_tcp),1421 __imm(bpf_sk_release),1422 __imm(bpf_skc_to_tcp_sock),1423 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1424 : __clobber_all);1425}1426 1427SEC("tc")1428__description("reference tracking: use ptr from bpf_skc_to_tcp_sock() after release")1429__failure __msg("invalid mem access")1430__naked void to_tcp_sock_after_release(void)1431{1432 asm volatile (1433 BPF_SK_LOOKUP(bpf_sk_lookup_tcp)1434" if r0 != 0 goto l0_%=; \1435 exit; \1436l0_%=: r6 = r0; \1437 r1 = r0; \1438 call %[bpf_skc_to_tcp_sock]; \1439 if r0 != 0 goto l1_%=; \1440 r1 = r6; \1441 call %[bpf_sk_release]; \1442 exit; \1443l1_%=: r7 = r0; \1444 r1 = r6; \1445 call %[bpf_sk_release]; \1446 r0 = *(u8*)(r7 + 0); \1447 exit; \1448" :1449 : __imm(bpf_sk_lookup_tcp),1450 __imm(bpf_sk_release),1451 __imm(bpf_skc_to_tcp_sock),1452 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple))1453 : __clobber_all);1454}1455 1456SEC("socket")1457__description("reference tracking: try to leak released ptr reg")1458__success __failure_unpriv __msg_unpriv("R8 !read_ok")1459__retval(0)1460__naked void to_leak_released_ptr_reg(void)1461{1462 asm volatile (" \1463 r0 = 0; \1464 *(u32*)(r10 - 4) = r0; \1465 r2 = r10; \1466 r2 += -4; \1467 r1 = %[map_array_48b] ll; \1468 call %[bpf_map_lookup_elem]; \1469 if r0 != 0 goto l0_%=; \1470 exit; \1471l0_%=: r9 = r0; \1472 r0 = 0; \1473 r1 = %[map_ringbuf] ll; \1474 r2 = 8; \1475 r3 = 0; \1476 call %[bpf_ringbuf_reserve]; \1477 if r0 != 0 goto l1_%=; \1478 exit; \1479l1_%=: r8 = r0; \1480 r1 = r8; \1481 r2 = 0; \1482 call %[bpf_ringbuf_discard]; \1483 r0 = 0; \1484 *(u64*)(r9 + 0) = r8; \1485 exit; \1486" :1487 : __imm(bpf_map_lookup_elem),1488 __imm(bpf_ringbuf_discard),1489 __imm(bpf_ringbuf_reserve),1490 __imm_addr(map_array_48b),1491 __imm_addr(map_ringbuf)1492 : __clobber_all);1493}1494 1495char _license[] SEC("license") = "GPL";1496