162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Converted from tools/testing/selftests/bpf/verifier/unpriv.c */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/bpf.h> 562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 662306a36Sopenharmony_ci#include "../../../include/linux/filter.h" 762306a36Sopenharmony_ci#include "bpf_misc.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define BPF_SK_LOOKUP(func) \ 1062306a36Sopenharmony_ci /* struct bpf_sock_tuple tuple = {} */ \ 1162306a36Sopenharmony_ci "r2 = 0;" \ 1262306a36Sopenharmony_ci "*(u32*)(r10 - 8) = r2;" \ 1362306a36Sopenharmony_ci "*(u64*)(r10 - 16) = r2;" \ 1462306a36Sopenharmony_ci "*(u64*)(r10 - 24) = r2;" \ 1562306a36Sopenharmony_ci "*(u64*)(r10 - 32) = r2;" \ 1662306a36Sopenharmony_ci "*(u64*)(r10 - 40) = r2;" \ 1762306a36Sopenharmony_ci "*(u64*)(r10 - 48) = r2;" \ 1862306a36Sopenharmony_ci /* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \ 1962306a36Sopenharmony_ci "r2 = r10;" \ 2062306a36Sopenharmony_ci "r2 += -48;" \ 2162306a36Sopenharmony_ci "r3 = %[sizeof_bpf_sock_tuple];"\ 2262306a36Sopenharmony_ci "r4 = 0;" \ 2362306a36Sopenharmony_ci "r5 = 0;" \ 2462306a36Sopenharmony_ci "call %[" #func "];" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct { 2762306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 2862306a36Sopenharmony_ci __uint(max_entries, 1); 2962306a36Sopenharmony_ci __type(key, long long); 3062306a36Sopenharmony_ci __type(value, long long); 3162306a36Sopenharmony_ci} map_hash_8b SEC(".maps"); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_civoid dummy_prog_42_socket(void); 3462306a36Sopenharmony_civoid dummy_prog_24_socket(void); 3562306a36Sopenharmony_civoid dummy_prog_loop1_socket(void); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct { 3862306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 3962306a36Sopenharmony_ci __uint(max_entries, 4); 4062306a36Sopenharmony_ci __uint(key_size, sizeof(int)); 4162306a36Sopenharmony_ci __array(values, void (void)); 4262306a36Sopenharmony_ci} map_prog1_socket SEC(".maps") = { 4362306a36Sopenharmony_ci .values = { 4462306a36Sopenharmony_ci [0] = (void *)&dummy_prog_42_socket, 4562306a36Sopenharmony_ci [1] = (void *)&dummy_prog_loop1_socket, 4662306a36Sopenharmony_ci [2] = (void *)&dummy_prog_24_socket, 4762306a36Sopenharmony_ci }, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciSEC("socket") 5162306a36Sopenharmony_ci__auxiliary __auxiliary_unpriv 5262306a36Sopenharmony_ci__naked void dummy_prog_42_socket(void) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci asm volatile ("r0 = 42; exit;"); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciSEC("socket") 5862306a36Sopenharmony_ci__auxiliary __auxiliary_unpriv 5962306a36Sopenharmony_ci__naked void dummy_prog_24_socket(void) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci asm volatile ("r0 = 24; exit;"); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciSEC("socket") 6562306a36Sopenharmony_ci__auxiliary __auxiliary_unpriv 6662306a36Sopenharmony_ci__naked void dummy_prog_loop1_socket(void) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci asm volatile (" \ 6962306a36Sopenharmony_ci r3 = 1; \ 7062306a36Sopenharmony_ci r2 = %[map_prog1_socket] ll; \ 7162306a36Sopenharmony_ci call %[bpf_tail_call]; \ 7262306a36Sopenharmony_ci r0 = 41; \ 7362306a36Sopenharmony_ci exit; \ 7462306a36Sopenharmony_ci" : 7562306a36Sopenharmony_ci : __imm(bpf_tail_call), 7662306a36Sopenharmony_ci __imm_addr(map_prog1_socket) 7762306a36Sopenharmony_ci : __clobber_all); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciSEC("socket") 8162306a36Sopenharmony_ci__description("unpriv: return pointer") 8262306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R0 leaks addr") 8362306a36Sopenharmony_ci__retval(POINTER_VALUE) 8462306a36Sopenharmony_ci__naked void unpriv_return_pointer(void) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci asm volatile (" \ 8762306a36Sopenharmony_ci r0 = r10; \ 8862306a36Sopenharmony_ci exit; \ 8962306a36Sopenharmony_ci" ::: __clobber_all); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciSEC("socket") 9362306a36Sopenharmony_ci__description("unpriv: add const to pointer") 9462306a36Sopenharmony_ci__success __success_unpriv __retval(0) 9562306a36Sopenharmony_ci__naked void unpriv_add_const_to_pointer(void) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci asm volatile (" \ 9862306a36Sopenharmony_ci r1 += 8; \ 9962306a36Sopenharmony_ci r0 = 0; \ 10062306a36Sopenharmony_ci exit; \ 10162306a36Sopenharmony_ci" ::: __clobber_all); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciSEC("socket") 10562306a36Sopenharmony_ci__description("unpriv: add pointer to pointer") 10662306a36Sopenharmony_ci__failure __msg("R1 pointer += pointer") 10762306a36Sopenharmony_ci__failure_unpriv 10862306a36Sopenharmony_ci__naked void unpriv_add_pointer_to_pointer(void) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci asm volatile (" \ 11162306a36Sopenharmony_ci r1 += r10; \ 11262306a36Sopenharmony_ci r0 = 0; \ 11362306a36Sopenharmony_ci exit; \ 11462306a36Sopenharmony_ci" ::: __clobber_all); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ciSEC("socket") 11862306a36Sopenharmony_ci__description("unpriv: neg pointer") 11962306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R1 pointer arithmetic") 12062306a36Sopenharmony_ci__retval(0) 12162306a36Sopenharmony_ci__naked void unpriv_neg_pointer(void) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci asm volatile (" \ 12462306a36Sopenharmony_ci r1 = -r1; \ 12562306a36Sopenharmony_ci r0 = 0; \ 12662306a36Sopenharmony_ci exit; \ 12762306a36Sopenharmony_ci" ::: __clobber_all); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciSEC("socket") 13162306a36Sopenharmony_ci__description("unpriv: cmp pointer with const") 13262306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R1 pointer comparison") 13362306a36Sopenharmony_ci__retval(0) 13462306a36Sopenharmony_ci__naked void unpriv_cmp_pointer_with_const(void) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci asm volatile (" \ 13762306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 13862306a36Sopenharmony_cil0_%=: r0 = 0; \ 13962306a36Sopenharmony_ci exit; \ 14062306a36Sopenharmony_ci" ::: __clobber_all); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciSEC("socket") 14462306a36Sopenharmony_ci__description("unpriv: cmp pointer with pointer") 14562306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R10 pointer comparison") 14662306a36Sopenharmony_ci__retval(0) 14762306a36Sopenharmony_ci__naked void unpriv_cmp_pointer_with_pointer(void) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci asm volatile (" \ 15062306a36Sopenharmony_ci if r1 == r10 goto l0_%=; \ 15162306a36Sopenharmony_cil0_%=: r0 = 0; \ 15262306a36Sopenharmony_ci exit; \ 15362306a36Sopenharmony_ci" ::: __clobber_all); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciSEC("tracepoint") 15762306a36Sopenharmony_ci__description("unpriv: check that printk is disallowed") 15862306a36Sopenharmony_ci__success 15962306a36Sopenharmony_ci__naked void check_that_printk_is_disallowed(void) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci asm volatile (" \ 16262306a36Sopenharmony_ci r1 = 0; \ 16362306a36Sopenharmony_ci *(u64*)(r10 - 8) = r1; \ 16462306a36Sopenharmony_ci r1 = r10; \ 16562306a36Sopenharmony_ci r1 += -8; \ 16662306a36Sopenharmony_ci r2 = 8; \ 16762306a36Sopenharmony_ci r3 = r1; \ 16862306a36Sopenharmony_ci call %[bpf_trace_printk]; \ 16962306a36Sopenharmony_ci r0 = 0; \ 17062306a36Sopenharmony_ci exit; \ 17162306a36Sopenharmony_ci" : 17262306a36Sopenharmony_ci : __imm(bpf_trace_printk) 17362306a36Sopenharmony_ci : __clobber_all); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciSEC("socket") 17762306a36Sopenharmony_ci__description("unpriv: pass pointer to helper function") 17862306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R4 leaks addr") 17962306a36Sopenharmony_ci__retval(0) 18062306a36Sopenharmony_ci__naked void pass_pointer_to_helper_function(void) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci asm volatile (" \ 18362306a36Sopenharmony_ci r1 = 0; \ 18462306a36Sopenharmony_ci *(u64*)(r10 - 8) = r1; \ 18562306a36Sopenharmony_ci r2 = r10; \ 18662306a36Sopenharmony_ci r2 += -8; \ 18762306a36Sopenharmony_ci r1 = %[map_hash_8b] ll; \ 18862306a36Sopenharmony_ci r3 = r2; \ 18962306a36Sopenharmony_ci r4 = r2; \ 19062306a36Sopenharmony_ci call %[bpf_map_update_elem]; \ 19162306a36Sopenharmony_ci r0 = 0; \ 19262306a36Sopenharmony_ci exit; \ 19362306a36Sopenharmony_ci" : 19462306a36Sopenharmony_ci : __imm(bpf_map_update_elem), 19562306a36Sopenharmony_ci __imm_addr(map_hash_8b) 19662306a36Sopenharmony_ci : __clobber_all); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciSEC("socket") 20062306a36Sopenharmony_ci__description("unpriv: indirectly pass pointer on stack to helper function") 20162306a36Sopenharmony_ci__success __failure_unpriv 20262306a36Sopenharmony_ci__msg_unpriv("invalid indirect read from stack R2 off -8+0 size 8") 20362306a36Sopenharmony_ci__retval(0) 20462306a36Sopenharmony_ci__naked void on_stack_to_helper_function(void) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci asm volatile (" \ 20762306a36Sopenharmony_ci *(u64*)(r10 - 8) = r10; \ 20862306a36Sopenharmony_ci r2 = r10; \ 20962306a36Sopenharmony_ci r2 += -8; \ 21062306a36Sopenharmony_ci r1 = %[map_hash_8b] ll; \ 21162306a36Sopenharmony_ci call %[bpf_map_lookup_elem]; \ 21262306a36Sopenharmony_ci r0 = 0; \ 21362306a36Sopenharmony_ci exit; \ 21462306a36Sopenharmony_ci" : 21562306a36Sopenharmony_ci : __imm(bpf_map_lookup_elem), 21662306a36Sopenharmony_ci __imm_addr(map_hash_8b) 21762306a36Sopenharmony_ci : __clobber_all); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ciSEC("socket") 22162306a36Sopenharmony_ci__description("unpriv: mangle pointer on stack 1") 22262306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled") 22362306a36Sopenharmony_ci__retval(0) 22462306a36Sopenharmony_ci__naked void mangle_pointer_on_stack_1(void) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci asm volatile (" \ 22762306a36Sopenharmony_ci *(u64*)(r10 - 8) = r10; \ 22862306a36Sopenharmony_ci r0 = 0; \ 22962306a36Sopenharmony_ci *(u32*)(r10 - 8) = r0; \ 23062306a36Sopenharmony_ci r0 = 0; \ 23162306a36Sopenharmony_ci exit; \ 23262306a36Sopenharmony_ci" ::: __clobber_all); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ciSEC("socket") 23662306a36Sopenharmony_ci__description("unpriv: mangle pointer on stack 2") 23762306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled") 23862306a36Sopenharmony_ci__retval(0) 23962306a36Sopenharmony_ci__naked void mangle_pointer_on_stack_2(void) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci asm volatile (" \ 24262306a36Sopenharmony_ci *(u64*)(r10 - 8) = r10; \ 24362306a36Sopenharmony_ci r0 = 0; \ 24462306a36Sopenharmony_ci *(u8*)(r10 - 1) = r0; \ 24562306a36Sopenharmony_ci r0 = 0; \ 24662306a36Sopenharmony_ci exit; \ 24762306a36Sopenharmony_ci" ::: __clobber_all); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciSEC("socket") 25162306a36Sopenharmony_ci__description("unpriv: read pointer from stack in small chunks") 25262306a36Sopenharmony_ci__failure __msg("invalid size") 25362306a36Sopenharmony_ci__failure_unpriv 25462306a36Sopenharmony_ci__naked void from_stack_in_small_chunks(void) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci asm volatile (" \ 25762306a36Sopenharmony_ci *(u64*)(r10 - 8) = r10; \ 25862306a36Sopenharmony_ci r0 = *(u32*)(r10 - 8); \ 25962306a36Sopenharmony_ci r0 = 0; \ 26062306a36Sopenharmony_ci exit; \ 26162306a36Sopenharmony_ci" ::: __clobber_all); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ciSEC("socket") 26562306a36Sopenharmony_ci__description("unpriv: write pointer into ctx") 26662306a36Sopenharmony_ci__failure __msg("invalid bpf_context access") 26762306a36Sopenharmony_ci__failure_unpriv __msg_unpriv("R1 leaks addr") 26862306a36Sopenharmony_ci__naked void unpriv_write_pointer_into_ctx(void) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci asm volatile (" \ 27162306a36Sopenharmony_ci *(u64*)(r1 + 0) = r1; \ 27262306a36Sopenharmony_ci r0 = 0; \ 27362306a36Sopenharmony_ci exit; \ 27462306a36Sopenharmony_ci" ::: __clobber_all); 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ciSEC("socket") 27862306a36Sopenharmony_ci__description("unpriv: spill/fill of ctx") 27962306a36Sopenharmony_ci__success __success_unpriv __retval(0) 28062306a36Sopenharmony_ci__naked void unpriv_spill_fill_of_ctx(void) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci asm volatile (" \ 28362306a36Sopenharmony_ci r6 = r10; \ 28462306a36Sopenharmony_ci r6 += -8; \ 28562306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 28662306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 28762306a36Sopenharmony_ci r0 = 0; \ 28862306a36Sopenharmony_ci exit; \ 28962306a36Sopenharmony_ci" ::: __clobber_all); 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciSEC("tc") 29362306a36Sopenharmony_ci__description("unpriv: spill/fill of ctx 2") 29462306a36Sopenharmony_ci__success __retval(0) 29562306a36Sopenharmony_ci__naked void spill_fill_of_ctx_2(void) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci asm volatile (" \ 29862306a36Sopenharmony_ci r6 = r10; \ 29962306a36Sopenharmony_ci r6 += -8; \ 30062306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 30162306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 30262306a36Sopenharmony_ci call %[bpf_get_hash_recalc]; \ 30362306a36Sopenharmony_ci r0 = 0; \ 30462306a36Sopenharmony_ci exit; \ 30562306a36Sopenharmony_ci" : 30662306a36Sopenharmony_ci : __imm(bpf_get_hash_recalc) 30762306a36Sopenharmony_ci : __clobber_all); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ciSEC("tc") 31162306a36Sopenharmony_ci__description("unpriv: spill/fill of ctx 3") 31262306a36Sopenharmony_ci__failure __msg("R1 type=fp expected=ctx") 31362306a36Sopenharmony_ci__naked void spill_fill_of_ctx_3(void) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci asm volatile (" \ 31662306a36Sopenharmony_ci r6 = r10; \ 31762306a36Sopenharmony_ci r6 += -8; \ 31862306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 31962306a36Sopenharmony_ci *(u64*)(r6 + 0) = r10; \ 32062306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 32162306a36Sopenharmony_ci call %[bpf_get_hash_recalc]; \ 32262306a36Sopenharmony_ci exit; \ 32362306a36Sopenharmony_ci" : 32462306a36Sopenharmony_ci : __imm(bpf_get_hash_recalc) 32562306a36Sopenharmony_ci : __clobber_all); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ciSEC("tc") 32962306a36Sopenharmony_ci__description("unpriv: spill/fill of ctx 4") 33062306a36Sopenharmony_ci__failure __msg("R1 type=scalar expected=ctx") 33162306a36Sopenharmony_ci__naked void spill_fill_of_ctx_4(void) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci asm volatile (" \ 33462306a36Sopenharmony_ci r6 = r10; \ 33562306a36Sopenharmony_ci r6 += -8; \ 33662306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 33762306a36Sopenharmony_ci r0 = 1; \ 33862306a36Sopenharmony_ci lock *(u64 *)(r10 - 8) += r0; \ 33962306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 34062306a36Sopenharmony_ci call %[bpf_get_hash_recalc]; \ 34162306a36Sopenharmony_ci exit; \ 34262306a36Sopenharmony_ci" : 34362306a36Sopenharmony_ci : __imm(bpf_get_hash_recalc) 34462306a36Sopenharmony_ci : __clobber_all); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ciSEC("tc") 34862306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers stx") 34962306a36Sopenharmony_ci__failure __msg("same insn cannot be used with different pointers") 35062306a36Sopenharmony_ci__naked void fill_of_different_pointers_stx(void) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci asm volatile (" \ 35362306a36Sopenharmony_ci r3 = 42; \ 35462306a36Sopenharmony_ci r6 = r10; \ 35562306a36Sopenharmony_ci r6 += -8; \ 35662306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 35762306a36Sopenharmony_ci r2 = r10; \ 35862306a36Sopenharmony_ci r2 += -16; \ 35962306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 36062306a36Sopenharmony_cil0_%=: if r1 != 0 goto l1_%=; \ 36162306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 36262306a36Sopenharmony_cil1_%=: r1 = *(u64*)(r6 + 0); \ 36362306a36Sopenharmony_ci *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 36462306a36Sopenharmony_ci r0 = 0; \ 36562306a36Sopenharmony_ci exit; \ 36662306a36Sopenharmony_ci" : 36762306a36Sopenharmony_ci : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 36862306a36Sopenharmony_ci : __clobber_all); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci/* Same as above, but use BPF_ST_MEM to save 42 37262306a36Sopenharmony_ci * instead of BPF_STX_MEM. 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ciSEC("tc") 37562306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers st") 37662306a36Sopenharmony_ci__failure __msg("same insn cannot be used with different pointers") 37762306a36Sopenharmony_ci__naked void fill_of_different_pointers_st(void) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci asm volatile (" \ 38062306a36Sopenharmony_ci r6 = r10; \ 38162306a36Sopenharmony_ci r6 += -8; \ 38262306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 38362306a36Sopenharmony_ci r2 = r10; \ 38462306a36Sopenharmony_ci r2 += -16; \ 38562306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 38662306a36Sopenharmony_cil0_%=: if r1 != 0 goto l1_%=; \ 38762306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 38862306a36Sopenharmony_cil1_%=: r1 = *(u64*)(r6 + 0); \ 38962306a36Sopenharmony_ci .8byte %[st_mem]; \ 39062306a36Sopenharmony_ci r0 = 0; \ 39162306a36Sopenharmony_ci exit; \ 39262306a36Sopenharmony_ci" : 39362306a36Sopenharmony_ci : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 39462306a36Sopenharmony_ci __imm_insn(st_mem, 39562306a36Sopenharmony_ci BPF_ST_MEM(BPF_W, BPF_REG_1, offsetof(struct __sk_buff, mark), 42)) 39662306a36Sopenharmony_ci : __clobber_all); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ciSEC("tc") 40062306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers stx - ctx and sock") 40162306a36Sopenharmony_ci__failure __msg("type=ctx expected=sock") 40262306a36Sopenharmony_ci__naked void pointers_stx_ctx_and_sock(void) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci asm volatile (" \ 40562306a36Sopenharmony_ci r8 = r1; \ 40662306a36Sopenharmony_ci /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 40762306a36Sopenharmony_ci" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 40862306a36Sopenharmony_ci" r2 = r0; \ 40962306a36Sopenharmony_ci /* u64 foo; */ \ 41062306a36Sopenharmony_ci /* void *target = &foo; */ \ 41162306a36Sopenharmony_ci r6 = r10; \ 41262306a36Sopenharmony_ci r6 += -8; \ 41362306a36Sopenharmony_ci r1 = r8; \ 41462306a36Sopenharmony_ci /* if (skb == NULL) *target = sock; */ \ 41562306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 41662306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 41762306a36Sopenharmony_cil0_%=: /* else *target = skb; */ \ 41862306a36Sopenharmony_ci if r1 != 0 goto l1_%=; \ 41962306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 42062306a36Sopenharmony_cil1_%=: /* struct __sk_buff *skb = *target; */ \ 42162306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 42262306a36Sopenharmony_ci /* skb->mark = 42; */ \ 42362306a36Sopenharmony_ci r3 = 42; \ 42462306a36Sopenharmony_ci *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 42562306a36Sopenharmony_ci /* if (sk) bpf_sk_release(sk) */ \ 42662306a36Sopenharmony_ci if r1 == 0 goto l2_%=; \ 42762306a36Sopenharmony_ci call %[bpf_sk_release]; \ 42862306a36Sopenharmony_cil2_%=: r0 = 0; \ 42962306a36Sopenharmony_ci exit; \ 43062306a36Sopenharmony_ci" : 43162306a36Sopenharmony_ci : __imm(bpf_sk_lookup_tcp), 43262306a36Sopenharmony_ci __imm(bpf_sk_release), 43362306a36Sopenharmony_ci __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 43462306a36Sopenharmony_ci __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 43562306a36Sopenharmony_ci : __clobber_all); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciSEC("tc") 43962306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers stx - leak sock") 44062306a36Sopenharmony_ci__failure 44162306a36Sopenharmony_ci//.errstr = "same insn cannot be used with different pointers", 44262306a36Sopenharmony_ci__msg("Unreleased reference") 44362306a36Sopenharmony_ci__naked void different_pointers_stx_leak_sock(void) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci asm volatile (" \ 44662306a36Sopenharmony_ci r8 = r1; \ 44762306a36Sopenharmony_ci /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 44862306a36Sopenharmony_ci" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 44962306a36Sopenharmony_ci" r2 = r0; \ 45062306a36Sopenharmony_ci /* u64 foo; */ \ 45162306a36Sopenharmony_ci /* void *target = &foo; */ \ 45262306a36Sopenharmony_ci r6 = r10; \ 45362306a36Sopenharmony_ci r6 += -8; \ 45462306a36Sopenharmony_ci r1 = r8; \ 45562306a36Sopenharmony_ci /* if (skb == NULL) *target = sock; */ \ 45662306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 45762306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 45862306a36Sopenharmony_cil0_%=: /* else *target = skb; */ \ 45962306a36Sopenharmony_ci if r1 != 0 goto l1_%=; \ 46062306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 46162306a36Sopenharmony_cil1_%=: /* struct __sk_buff *skb = *target; */ \ 46262306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 46362306a36Sopenharmony_ci /* skb->mark = 42; */ \ 46462306a36Sopenharmony_ci r3 = 42; \ 46562306a36Sopenharmony_ci *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 46662306a36Sopenharmony_ci exit; \ 46762306a36Sopenharmony_ci" : 46862306a36Sopenharmony_ci : __imm(bpf_sk_lookup_tcp), 46962306a36Sopenharmony_ci __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 47062306a36Sopenharmony_ci __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 47162306a36Sopenharmony_ci : __clobber_all); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ciSEC("tc") 47562306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers stx - sock and ctx (read)") 47662306a36Sopenharmony_ci__failure __msg("same insn cannot be used with different pointers") 47762306a36Sopenharmony_ci__naked void stx_sock_and_ctx_read(void) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci asm volatile (" \ 48062306a36Sopenharmony_ci r8 = r1; \ 48162306a36Sopenharmony_ci /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 48262306a36Sopenharmony_ci" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 48362306a36Sopenharmony_ci" r2 = r0; \ 48462306a36Sopenharmony_ci /* u64 foo; */ \ 48562306a36Sopenharmony_ci /* void *target = &foo; */ \ 48662306a36Sopenharmony_ci r6 = r10; \ 48762306a36Sopenharmony_ci r6 += -8; \ 48862306a36Sopenharmony_ci r1 = r8; \ 48962306a36Sopenharmony_ci /* if (skb) *target = skb */ \ 49062306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 49162306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 49262306a36Sopenharmony_cil0_%=: /* else *target = sock */ \ 49362306a36Sopenharmony_ci if r1 != 0 goto l1_%=; \ 49462306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 49562306a36Sopenharmony_cil1_%=: /* struct bpf_sock *sk = *target; */ \ 49662306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 49762306a36Sopenharmony_ci /* if (sk) u32 foo = sk->mark; bpf_sk_release(sk); */\ 49862306a36Sopenharmony_ci if r1 == 0 goto l2_%=; \ 49962306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[bpf_sock_mark]); \ 50062306a36Sopenharmony_ci call %[bpf_sk_release]; \ 50162306a36Sopenharmony_cil2_%=: r0 = 0; \ 50262306a36Sopenharmony_ci exit; \ 50362306a36Sopenharmony_ci" : 50462306a36Sopenharmony_ci : __imm(bpf_sk_lookup_tcp), 50562306a36Sopenharmony_ci __imm(bpf_sk_release), 50662306a36Sopenharmony_ci __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), 50762306a36Sopenharmony_ci __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 50862306a36Sopenharmony_ci : __clobber_all); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ciSEC("tc") 51262306a36Sopenharmony_ci__description("unpriv: spill/fill of different pointers stx - sock and ctx (write)") 51362306a36Sopenharmony_ci__failure 51462306a36Sopenharmony_ci//.errstr = "same insn cannot be used with different pointers", 51562306a36Sopenharmony_ci__msg("cannot write into sock") 51662306a36Sopenharmony_ci__naked void stx_sock_and_ctx_write(void) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci asm volatile (" \ 51962306a36Sopenharmony_ci r8 = r1; \ 52062306a36Sopenharmony_ci /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 52162306a36Sopenharmony_ci" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 52262306a36Sopenharmony_ci" r2 = r0; \ 52362306a36Sopenharmony_ci /* u64 foo; */ \ 52462306a36Sopenharmony_ci /* void *target = &foo; */ \ 52562306a36Sopenharmony_ci r6 = r10; \ 52662306a36Sopenharmony_ci r6 += -8; \ 52762306a36Sopenharmony_ci r1 = r8; \ 52862306a36Sopenharmony_ci /* if (skb) *target = skb */ \ 52962306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 53062306a36Sopenharmony_ci *(u64*)(r6 + 0) = r1; \ 53162306a36Sopenharmony_cil0_%=: /* else *target = sock */ \ 53262306a36Sopenharmony_ci if r1 != 0 goto l1_%=; \ 53362306a36Sopenharmony_ci *(u64*)(r6 + 0) = r2; \ 53462306a36Sopenharmony_cil1_%=: /* struct bpf_sock *sk = *target; */ \ 53562306a36Sopenharmony_ci r1 = *(u64*)(r6 + 0); \ 53662306a36Sopenharmony_ci /* if (sk) sk->mark = 42; bpf_sk_release(sk); */\ 53762306a36Sopenharmony_ci if r1 == 0 goto l2_%=; \ 53862306a36Sopenharmony_ci r3 = 42; \ 53962306a36Sopenharmony_ci *(u32*)(r1 + %[bpf_sock_mark]) = r3; \ 54062306a36Sopenharmony_ci call %[bpf_sk_release]; \ 54162306a36Sopenharmony_cil2_%=: r0 = 0; \ 54262306a36Sopenharmony_ci exit; \ 54362306a36Sopenharmony_ci" : 54462306a36Sopenharmony_ci : __imm(bpf_sk_lookup_tcp), 54562306a36Sopenharmony_ci __imm(bpf_sk_release), 54662306a36Sopenharmony_ci __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), 54762306a36Sopenharmony_ci __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 54862306a36Sopenharmony_ci : __clobber_all); 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ciSEC("socket") 55262306a36Sopenharmony_ci__description("unpriv: write pointer into map elem value") 55362306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R0 leaks addr") 55462306a36Sopenharmony_ci__retval(0) 55562306a36Sopenharmony_ci__naked void pointer_into_map_elem_value(void) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci asm volatile (" \ 55862306a36Sopenharmony_ci r1 = 0; \ 55962306a36Sopenharmony_ci *(u64*)(r10 - 8) = r1; \ 56062306a36Sopenharmony_ci r2 = r10; \ 56162306a36Sopenharmony_ci r2 += -8; \ 56262306a36Sopenharmony_ci r1 = %[map_hash_8b] ll; \ 56362306a36Sopenharmony_ci call %[bpf_map_lookup_elem]; \ 56462306a36Sopenharmony_ci if r0 == 0 goto l0_%=; \ 56562306a36Sopenharmony_ci *(u64*)(r0 + 0) = r0; \ 56662306a36Sopenharmony_cil0_%=: exit; \ 56762306a36Sopenharmony_ci" : 56862306a36Sopenharmony_ci : __imm(bpf_map_lookup_elem), 56962306a36Sopenharmony_ci __imm_addr(map_hash_8b) 57062306a36Sopenharmony_ci : __clobber_all); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ciSEC("socket") 57462306a36Sopenharmony_ci__description("alu32: mov u32 const") 57562306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R7 invalid mem access 'scalar'") 57662306a36Sopenharmony_ci__retval(0) 57762306a36Sopenharmony_ci__naked void alu32_mov_u32_const(void) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci asm volatile (" \ 58062306a36Sopenharmony_ci w7 = 0; \ 58162306a36Sopenharmony_ci w7 &= 1; \ 58262306a36Sopenharmony_ci w0 = w7; \ 58362306a36Sopenharmony_ci if r0 == 0 goto l0_%=; \ 58462306a36Sopenharmony_ci r0 = *(u64*)(r7 + 0); \ 58562306a36Sopenharmony_cil0_%=: exit; \ 58662306a36Sopenharmony_ci" ::: __clobber_all); 58762306a36Sopenharmony_ci} 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ciSEC("socket") 59062306a36Sopenharmony_ci__description("unpriv: partial copy of pointer") 59162306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R10 partial copy") 59262306a36Sopenharmony_ci__retval(0) 59362306a36Sopenharmony_ci__naked void unpriv_partial_copy_of_pointer(void) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci asm volatile (" \ 59662306a36Sopenharmony_ci w1 = w10; \ 59762306a36Sopenharmony_ci r0 = 0; \ 59862306a36Sopenharmony_ci exit; \ 59962306a36Sopenharmony_ci" ::: __clobber_all); 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ciSEC("socket") 60362306a36Sopenharmony_ci__description("unpriv: pass pointer to tail_call") 60462306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R3 leaks addr into helper") 60562306a36Sopenharmony_ci__retval(0) 60662306a36Sopenharmony_ci__naked void pass_pointer_to_tail_call(void) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci asm volatile (" \ 60962306a36Sopenharmony_ci r3 = r1; \ 61062306a36Sopenharmony_ci r2 = %[map_prog1_socket] ll; \ 61162306a36Sopenharmony_ci call %[bpf_tail_call]; \ 61262306a36Sopenharmony_ci r0 = 0; \ 61362306a36Sopenharmony_ci exit; \ 61462306a36Sopenharmony_ci" : 61562306a36Sopenharmony_ci : __imm(bpf_tail_call), 61662306a36Sopenharmony_ci __imm_addr(map_prog1_socket) 61762306a36Sopenharmony_ci : __clobber_all); 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ciSEC("socket") 62162306a36Sopenharmony_ci__description("unpriv: cmp map pointer with zero") 62262306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R1 pointer comparison") 62362306a36Sopenharmony_ci__retval(0) 62462306a36Sopenharmony_ci__naked void cmp_map_pointer_with_zero(void) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci asm volatile (" \ 62762306a36Sopenharmony_ci r1 = 0; \ 62862306a36Sopenharmony_ci r1 = %[map_hash_8b] ll; \ 62962306a36Sopenharmony_ci if r1 == 0 goto l0_%=; \ 63062306a36Sopenharmony_cil0_%=: r0 = 0; \ 63162306a36Sopenharmony_ci exit; \ 63262306a36Sopenharmony_ci" : 63362306a36Sopenharmony_ci : __imm_addr(map_hash_8b) 63462306a36Sopenharmony_ci : __clobber_all); 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ciSEC("socket") 63862306a36Sopenharmony_ci__description("unpriv: write into frame pointer") 63962306a36Sopenharmony_ci__failure __msg("frame pointer is read only") 64062306a36Sopenharmony_ci__failure_unpriv 64162306a36Sopenharmony_ci__naked void unpriv_write_into_frame_pointer(void) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci asm volatile (" \ 64462306a36Sopenharmony_ci r10 = r1; \ 64562306a36Sopenharmony_ci r0 = 0; \ 64662306a36Sopenharmony_ci exit; \ 64762306a36Sopenharmony_ci" ::: __clobber_all); 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ciSEC("socket") 65162306a36Sopenharmony_ci__description("unpriv: spill/fill frame pointer") 65262306a36Sopenharmony_ci__failure __msg("frame pointer is read only") 65362306a36Sopenharmony_ci__failure_unpriv 65462306a36Sopenharmony_ci__naked void unpriv_spill_fill_frame_pointer(void) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci asm volatile (" \ 65762306a36Sopenharmony_ci r6 = r10; \ 65862306a36Sopenharmony_ci r6 += -8; \ 65962306a36Sopenharmony_ci *(u64*)(r6 + 0) = r10; \ 66062306a36Sopenharmony_ci r10 = *(u64*)(r6 + 0); \ 66162306a36Sopenharmony_ci r0 = 0; \ 66262306a36Sopenharmony_ci exit; \ 66362306a36Sopenharmony_ci" ::: __clobber_all); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ciSEC("socket") 66762306a36Sopenharmony_ci__description("unpriv: cmp of frame pointer") 66862306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R10 pointer comparison") 66962306a36Sopenharmony_ci__retval(0) 67062306a36Sopenharmony_ci__naked void unpriv_cmp_of_frame_pointer(void) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci asm volatile (" \ 67362306a36Sopenharmony_ci if r10 == 0 goto l0_%=; \ 67462306a36Sopenharmony_cil0_%=: r0 = 0; \ 67562306a36Sopenharmony_ci exit; \ 67662306a36Sopenharmony_ci" ::: __clobber_all); 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ciSEC("socket") 68062306a36Sopenharmony_ci__description("unpriv: adding of fp, reg") 68162306a36Sopenharmony_ci__success __failure_unpriv 68262306a36Sopenharmony_ci__msg_unpriv("R1 stack pointer arithmetic goes out of range") 68362306a36Sopenharmony_ci__retval(0) 68462306a36Sopenharmony_ci__naked void unpriv_adding_of_fp_reg(void) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci asm volatile (" \ 68762306a36Sopenharmony_ci r0 = 0; \ 68862306a36Sopenharmony_ci r1 = 0; \ 68962306a36Sopenharmony_ci r1 += r10; \ 69062306a36Sopenharmony_ci *(u64*)(r1 - 8) = r0; \ 69162306a36Sopenharmony_ci exit; \ 69262306a36Sopenharmony_ci" ::: __clobber_all); 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ciSEC("socket") 69662306a36Sopenharmony_ci__description("unpriv: adding of fp, imm") 69762306a36Sopenharmony_ci__success __failure_unpriv 69862306a36Sopenharmony_ci__msg_unpriv("R1 stack pointer arithmetic goes out of range") 69962306a36Sopenharmony_ci__retval(0) 70062306a36Sopenharmony_ci__naked void unpriv_adding_of_fp_imm(void) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci asm volatile (" \ 70362306a36Sopenharmony_ci r0 = 0; \ 70462306a36Sopenharmony_ci r1 = r10; \ 70562306a36Sopenharmony_ci r1 += 0; \ 70662306a36Sopenharmony_ci *(u64*)(r1 - 8) = r0; \ 70762306a36Sopenharmony_ci exit; \ 70862306a36Sopenharmony_ci" ::: __clobber_all); 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ciSEC("socket") 71262306a36Sopenharmony_ci__description("unpriv: cmp of stack pointer") 71362306a36Sopenharmony_ci__success __failure_unpriv __msg_unpriv("R2 pointer comparison") 71462306a36Sopenharmony_ci__retval(0) 71562306a36Sopenharmony_ci__naked void unpriv_cmp_of_stack_pointer(void) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci asm volatile (" \ 71862306a36Sopenharmony_ci r2 = r10; \ 71962306a36Sopenharmony_ci r2 += -8; \ 72062306a36Sopenharmony_ci if r2 == 0 goto l0_%=; \ 72162306a36Sopenharmony_cil0_%=: r0 = 0; \ 72262306a36Sopenharmony_ci exit; \ 72362306a36Sopenharmony_ci" ::: __clobber_all); 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 727