1*03391494SEduard Zingerman // SPDX-License-Identifier: GPL-2.0 2*03391494SEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/value_adj_spill.c */ 3*03391494SEduard Zingerman 4*03391494SEduard Zingerman #include <linux/bpf.h> 5*03391494SEduard Zingerman #include <bpf/bpf_helpers.h> 6*03391494SEduard Zingerman #include "bpf_misc.h" 7*03391494SEduard Zingerman 8*03391494SEduard Zingerman #define MAX_ENTRIES 11 9*03391494SEduard Zingerman 10*03391494SEduard Zingerman struct test_val { 11*03391494SEduard Zingerman unsigned int index; 12*03391494SEduard Zingerman int foo[MAX_ENTRIES]; 13*03391494SEduard Zingerman }; 14*03391494SEduard Zingerman 15*03391494SEduard Zingerman struct { 16*03391494SEduard Zingerman __uint(type, BPF_MAP_TYPE_HASH); 17*03391494SEduard Zingerman __uint(max_entries, 1); 18*03391494SEduard Zingerman __type(key, long long); 19*03391494SEduard Zingerman __type(value, struct test_val); 20*03391494SEduard Zingerman } map_hash_48b SEC(".maps"); 21*03391494SEduard Zingerman 22*03391494SEduard Zingerman SEC("socket") 23*03391494SEduard Zingerman __description("map element value is preserved across register spilling") 24*03391494SEduard Zingerman __success __failure_unpriv __msg_unpriv("R0 leaks addr") 25*03391494SEduard Zingerman __retval(0) is_preserved_across_register_spilling(void)26*03391494SEduard Zingerman__naked void is_preserved_across_register_spilling(void) 27*03391494SEduard Zingerman { 28*03391494SEduard Zingerman asm volatile (" \ 29*03391494SEduard Zingerman r2 = r10; \ 30*03391494SEduard Zingerman r2 += -8; \ 31*03391494SEduard Zingerman r1 = 0; \ 32*03391494SEduard Zingerman *(u64*)(r2 + 0) = r1; \ 33*03391494SEduard Zingerman r1 = %[map_hash_48b] ll; \ 34*03391494SEduard Zingerman call %[bpf_map_lookup_elem]; \ 35*03391494SEduard Zingerman if r0 == 0 goto l0_%=; \ 36*03391494SEduard Zingerman r1 = 42; \ 37*03391494SEduard Zingerman *(u64*)(r0 + 0) = r1; \ 38*03391494SEduard Zingerman r1 = r10; \ 39*03391494SEduard Zingerman r1 += -184; \ 40*03391494SEduard Zingerman *(u64*)(r1 + 0) = r0; \ 41*03391494SEduard Zingerman r3 = *(u64*)(r1 + 0); \ 42*03391494SEduard Zingerman r1 = 42; \ 43*03391494SEduard Zingerman *(u64*)(r3 + 0) = r1; \ 44*03391494SEduard Zingerman l0_%=: exit; \ 45*03391494SEduard Zingerman " : 46*03391494SEduard Zingerman : __imm(bpf_map_lookup_elem), 47*03391494SEduard Zingerman __imm_addr(map_hash_48b) 48*03391494SEduard Zingerman : __clobber_all); 49*03391494SEduard Zingerman } 50*03391494SEduard Zingerman 51*03391494SEduard Zingerman SEC("socket") 52*03391494SEduard Zingerman __description("map element value or null is marked on register spilling") 53*03391494SEduard Zingerman __success __failure_unpriv __msg_unpriv("R0 leaks addr") 54*03391494SEduard Zingerman __retval(0) is_marked_on_register_spilling(void)55*03391494SEduard Zingerman__naked void is_marked_on_register_spilling(void) 56*03391494SEduard Zingerman { 57*03391494SEduard Zingerman asm volatile (" \ 58*03391494SEduard Zingerman r2 = r10; \ 59*03391494SEduard Zingerman r2 += -8; \ 60*03391494SEduard Zingerman r1 = 0; \ 61*03391494SEduard Zingerman *(u64*)(r2 + 0) = r1; \ 62*03391494SEduard Zingerman r1 = %[map_hash_48b] ll; \ 63*03391494SEduard Zingerman call %[bpf_map_lookup_elem]; \ 64*03391494SEduard Zingerman r1 = r10; \ 65*03391494SEduard Zingerman r1 += -152; \ 66*03391494SEduard Zingerman *(u64*)(r1 + 0) = r0; \ 67*03391494SEduard Zingerman if r0 == 0 goto l0_%=; \ 68*03391494SEduard Zingerman r3 = *(u64*)(r1 + 0); \ 69*03391494SEduard Zingerman r1 = 42; \ 70*03391494SEduard Zingerman *(u64*)(r3 + 0) = r1; \ 71*03391494SEduard Zingerman l0_%=: exit; \ 72*03391494SEduard Zingerman " : 73*03391494SEduard Zingerman : __imm(bpf_map_lookup_elem), 74*03391494SEduard Zingerman __imm_addr(map_hash_48b) 75*03391494SEduard Zingerman : __clobber_all); 76*03391494SEduard Zingerman } 77*03391494SEduard Zingerman 78*03391494SEduard Zingerman char _license[] SEC("license") = "GPL"; 79