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