1*8f59e87aSEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*8f59e87aSEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/value.c */
3*8f59e87aSEduard Zingerman 
4*8f59e87aSEduard Zingerman #include <linux/bpf.h>
5*8f59e87aSEduard Zingerman #include <bpf/bpf_helpers.h>
6*8f59e87aSEduard Zingerman #include "bpf_misc.h"
7*8f59e87aSEduard Zingerman 
8*8f59e87aSEduard Zingerman #define MAX_ENTRIES 11
9*8f59e87aSEduard Zingerman 
10*8f59e87aSEduard Zingerman struct test_val {
11*8f59e87aSEduard Zingerman 	unsigned int index;
12*8f59e87aSEduard Zingerman 	int foo[MAX_ENTRIES];
13*8f59e87aSEduard Zingerman };
14*8f59e87aSEduard Zingerman 
15*8f59e87aSEduard Zingerman struct {
16*8f59e87aSEduard Zingerman 	__uint(type, BPF_MAP_TYPE_HASH);
17*8f59e87aSEduard Zingerman 	__uint(max_entries, 1);
18*8f59e87aSEduard Zingerman 	__type(key, long long);
19*8f59e87aSEduard Zingerman 	__type(value, struct test_val);
20*8f59e87aSEduard Zingerman } map_hash_48b SEC(".maps");
21*8f59e87aSEduard Zingerman 
22*8f59e87aSEduard Zingerman SEC("socket")
23*8f59e87aSEduard Zingerman __description("map element value store of cleared call register")
24*8f59e87aSEduard Zingerman __failure __msg("R1 !read_ok")
25*8f59e87aSEduard Zingerman __failure_unpriv __msg_unpriv("R1 !read_ok")
store_of_cleared_call_register(void)26*8f59e87aSEduard Zingerman __naked void store_of_cleared_call_register(void)
27*8f59e87aSEduard Zingerman {
28*8f59e87aSEduard Zingerman 	asm volatile ("					\
29*8f59e87aSEduard Zingerman 	r2 = r10;					\
30*8f59e87aSEduard Zingerman 	r2 += -8;					\
31*8f59e87aSEduard Zingerman 	r1 = 0;						\
32*8f59e87aSEduard Zingerman 	*(u64*)(r2 + 0) = r1;				\
33*8f59e87aSEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
34*8f59e87aSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
35*8f59e87aSEduard Zingerman 	if r0 == 0 goto l0_%=;				\
36*8f59e87aSEduard Zingerman 	*(u64*)(r0 + 0) = r1;				\
37*8f59e87aSEduard Zingerman l0_%=:	exit;						\
38*8f59e87aSEduard Zingerman "	:
39*8f59e87aSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
40*8f59e87aSEduard Zingerman 	  __imm_addr(map_hash_48b)
41*8f59e87aSEduard Zingerman 	: __clobber_all);
42*8f59e87aSEduard Zingerman }
43*8f59e87aSEduard Zingerman 
44*8f59e87aSEduard Zingerman SEC("socket")
45*8f59e87aSEduard Zingerman __description("map element value with unaligned store")
46*8f59e87aSEduard Zingerman __success __failure_unpriv __msg_unpriv("R0 leaks addr")
__flag(BPF_F_ANY_ALIGNMENT)47*8f59e87aSEduard Zingerman __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
48*8f59e87aSEduard Zingerman __naked void element_value_with_unaligned_store(void)
49*8f59e87aSEduard Zingerman {
50*8f59e87aSEduard Zingerman 	asm volatile ("					\
51*8f59e87aSEduard Zingerman 	r2 = r10;					\
52*8f59e87aSEduard Zingerman 	r2 += -8;					\
53*8f59e87aSEduard Zingerman 	r1 = 0;						\
54*8f59e87aSEduard Zingerman 	*(u64*)(r2 + 0) = r1;				\
55*8f59e87aSEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
56*8f59e87aSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
57*8f59e87aSEduard Zingerman 	if r0 == 0 goto l0_%=;				\
58*8f59e87aSEduard Zingerman 	r0 += 3;					\
59*8f59e87aSEduard Zingerman 	r1 = 42;					\
60*8f59e87aSEduard Zingerman 	*(u64*)(r0 + 0) = r1;				\
61*8f59e87aSEduard Zingerman 	r1 = 43;					\
62*8f59e87aSEduard Zingerman 	*(u64*)(r0 + 2) = r1;				\
63*8f59e87aSEduard Zingerman 	r1 = 44;					\
64*8f59e87aSEduard Zingerman 	*(u64*)(r0 - 2) = r1;				\
65*8f59e87aSEduard Zingerman 	r8 = r0;					\
66*8f59e87aSEduard Zingerman 	r1 = 32;					\
67*8f59e87aSEduard Zingerman 	*(u64*)(r8 + 0) = r1;				\
68*8f59e87aSEduard Zingerman 	r1 = 33;					\
69*8f59e87aSEduard Zingerman 	*(u64*)(r8 + 2) = r1;				\
70*8f59e87aSEduard Zingerman 	r1 = 34;					\
71*8f59e87aSEduard Zingerman 	*(u64*)(r8 - 2) = r1;				\
72*8f59e87aSEduard Zingerman 	r8 += 5;					\
73*8f59e87aSEduard Zingerman 	r1 = 22;					\
74*8f59e87aSEduard Zingerman 	*(u64*)(r8 + 0) = r1;				\
75*8f59e87aSEduard Zingerman 	r1 = 23;					\
76*8f59e87aSEduard Zingerman 	*(u64*)(r8 + 4) = r1;				\
77*8f59e87aSEduard Zingerman 	r1 = 24;					\
78*8f59e87aSEduard Zingerman 	*(u64*)(r8 - 7) = r1;				\
79*8f59e87aSEduard Zingerman 	r7 = r8;					\
80*8f59e87aSEduard Zingerman 	r7 += 3;					\
81*8f59e87aSEduard Zingerman 	r1 = 22;					\
82*8f59e87aSEduard Zingerman 	*(u64*)(r7 + 0) = r1;				\
83*8f59e87aSEduard Zingerman 	r1 = 23;					\
84*8f59e87aSEduard Zingerman 	*(u64*)(r7 + 4) = r1;				\
85*8f59e87aSEduard Zingerman 	r1 = 24;					\
86*8f59e87aSEduard Zingerman 	*(u64*)(r7 - 4) = r1;				\
87*8f59e87aSEduard Zingerman l0_%=:	exit;						\
88*8f59e87aSEduard Zingerman "	:
89*8f59e87aSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
90*8f59e87aSEduard Zingerman 	  __imm_addr(map_hash_48b)
91*8f59e87aSEduard Zingerman 	: __clobber_all);
92*8f59e87aSEduard Zingerman }
93*8f59e87aSEduard Zingerman 
94*8f59e87aSEduard Zingerman SEC("socket")
95*8f59e87aSEduard Zingerman __description("map element value with unaligned load")
96*8f59e87aSEduard Zingerman __success __failure_unpriv __msg_unpriv("R0 leaks addr")
__flag(BPF_F_ANY_ALIGNMENT)97*8f59e87aSEduard Zingerman __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
98*8f59e87aSEduard Zingerman __naked void element_value_with_unaligned_load(void)
99*8f59e87aSEduard Zingerman {
100*8f59e87aSEduard Zingerman 	asm volatile ("					\
101*8f59e87aSEduard Zingerman 	r2 = r10;					\
102*8f59e87aSEduard Zingerman 	r2 += -8;					\
103*8f59e87aSEduard Zingerman 	r1 = 0;						\
104*8f59e87aSEduard Zingerman 	*(u64*)(r2 + 0) = r1;				\
105*8f59e87aSEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
106*8f59e87aSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
107*8f59e87aSEduard Zingerman 	if r0 == 0 goto l0_%=;				\
108*8f59e87aSEduard Zingerman 	r1 = *(u32*)(r0 + 0);				\
109*8f59e87aSEduard Zingerman 	if r1 >= %[max_entries] goto l0_%=;		\
110*8f59e87aSEduard Zingerman 	r0 += 3;					\
111*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r0 + 0);				\
112*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r0 + 2);				\
113*8f59e87aSEduard Zingerman 	r8 = r0;					\
114*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r8 + 0);				\
115*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r8 + 2);				\
116*8f59e87aSEduard Zingerman 	r0 += 5;					\
117*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r0 + 0);				\
118*8f59e87aSEduard Zingerman 	r7 = *(u64*)(r0 + 4);				\
119*8f59e87aSEduard Zingerman l0_%=:	exit;						\
120*8f59e87aSEduard Zingerman "	:
121*8f59e87aSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
122*8f59e87aSEduard Zingerman 	  __imm_addr(map_hash_48b),
123*8f59e87aSEduard Zingerman 	  __imm_const(max_entries, MAX_ENTRIES)
124*8f59e87aSEduard Zingerman 	: __clobber_all);
125*8f59e87aSEduard Zingerman }
126*8f59e87aSEduard Zingerman 
127*8f59e87aSEduard Zingerman SEC("socket")
128*8f59e87aSEduard Zingerman __description("map element value is preserved across register spilling")
129*8f59e87aSEduard Zingerman __success __failure_unpriv __msg_unpriv("R0 leaks addr")
__flag(BPF_F_ANY_ALIGNMENT)130*8f59e87aSEduard Zingerman __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
131*8f59e87aSEduard Zingerman __naked void is_preserved_across_register_spilling(void)
132*8f59e87aSEduard Zingerman {
133*8f59e87aSEduard Zingerman 	asm volatile ("					\
134*8f59e87aSEduard Zingerman 	r2 = r10;					\
135*8f59e87aSEduard Zingerman 	r2 += -8;					\
136*8f59e87aSEduard Zingerman 	r1 = 0;						\
137*8f59e87aSEduard Zingerman 	*(u64*)(r2 + 0) = r1;				\
138*8f59e87aSEduard Zingerman 	r1 = %[map_hash_48b] ll;			\
139*8f59e87aSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
140*8f59e87aSEduard Zingerman 	if r0 == 0 goto l0_%=;				\
141*8f59e87aSEduard Zingerman 	r0 += %[test_val_foo];				\
142*8f59e87aSEduard Zingerman 	r1 = 42;					\
143*8f59e87aSEduard Zingerman 	*(u64*)(r0 + 0) = r1;				\
144*8f59e87aSEduard Zingerman 	r1 = r10;					\
145*8f59e87aSEduard Zingerman 	r1 += -184;					\
146*8f59e87aSEduard Zingerman 	*(u64*)(r1 + 0) = r0;				\
147*8f59e87aSEduard Zingerman 	r3 = *(u64*)(r1 + 0);				\
148*8f59e87aSEduard Zingerman 	r1 = 42;					\
149*8f59e87aSEduard Zingerman 	*(u64*)(r3 + 0) = r1;				\
150*8f59e87aSEduard Zingerman l0_%=:	exit;						\
151*8f59e87aSEduard Zingerman "	:
152*8f59e87aSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
153*8f59e87aSEduard Zingerman 	  __imm_addr(map_hash_48b),
154*8f59e87aSEduard Zingerman 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
155*8f59e87aSEduard Zingerman 	: __clobber_all);
156*8f59e87aSEduard Zingerman }
157*8f59e87aSEduard Zingerman 
158*8f59e87aSEduard Zingerman char _license[] SEC("license") = "GPL";
159