1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/regalloc.c */
5 #include <bpf/bpf_helpers.h>
16 __uint(type, BPF_MAP_TYPE_HASH);
17 __uint(max_entries, 1);
18 __type(key, long long);
19 __type(value, struct test_val);
20 } map_hash_48b SEC(".maps");
23 __description("regalloc basic")
24 __success __flag(BPF_F_ANY_ALIGNMENT)
25 __naked void regalloc_basic(void)
30 *(u64*)(r10 - 8) = r1; \
33 r1 = %[map_hash_48b] ll; \
34 call %[bpf_map_lookup_elem]; \
35 if r0 == 0 goto l0_%=; \
37 call %[bpf_get_prandom_u32]; \
39 if r0 s> 20 goto l0_%=; \
40 if r2 s< 0 goto l0_%=; \
43 r0 = *(u64*)(r7 + 0); \
46 : __imm(bpf_get_prandom_u32),
47 __imm(bpf_map_lookup_elem),
48 __imm_addr(map_hash_48b)
53 __description("regalloc negative")
54 __failure __msg("invalid access to map value, value_size=48 off=48 size=1")
55 __naked void regalloc_negative(void)
60 *(u64*)(r10 - 8) = r1; \
63 r1 = %[map_hash_48b] ll; \
64 call %[bpf_map_lookup_elem]; \
65 if r0 == 0 goto l0_%=; \
67 call %[bpf_get_prandom_u32]; \
69 if r0 s> 24 goto l0_%=; \
70 if r2 s< 0 goto l0_%=; \
73 r0 = *(u8*)(r7 + 0); \
76 : __imm(bpf_get_prandom_u32),
77 __imm(bpf_map_lookup_elem),
78 __imm_addr(map_hash_48b)
83 __description("regalloc src_reg mark")
84 __success __flag(BPF_F_ANY_ALIGNMENT)
85 __naked void regalloc_src_reg_mark(void)
90 *(u64*)(r10 - 8) = r1; \
93 r1 = %[map_hash_48b] ll; \
94 call %[bpf_map_lookup_elem]; \
95 if r0 == 0 goto l0_%=; \
97 call %[bpf_get_prandom_u32]; \
99 if r0 s> 20 goto l0_%=; \
101 if r3 s>= r2 goto l0_%=; \
104 r0 = *(u64*)(r7 + 0); \
107 : __imm(bpf_get_prandom_u32),
108 __imm(bpf_map_lookup_elem),
109 __imm_addr(map_hash_48b)
114 __description("regalloc src_reg negative")
115 __failure __msg("invalid access to map value, value_size=48 off=44 size=8")
116 __flag(BPF_F_ANY_ALIGNMENT)
117 __naked void regalloc_src_reg_negative(void)
122 *(u64*)(r10 - 8) = r1; \
125 r1 = %[map_hash_48b] ll; \
126 call %[bpf_map_lookup_elem]; \
127 if r0 == 0 goto l0_%=; \
129 call %[bpf_get_prandom_u32]; \
131 if r0 s> 22 goto l0_%=; \
133 if r3 s>= r2 goto l0_%=; \
136 r0 = *(u64*)(r7 + 0); \
139 : __imm(bpf_get_prandom_u32),
140 __imm(bpf_map_lookup_elem),
141 __imm_addr(map_hash_48b)
146 __description("regalloc and spill")
147 __success __flag(BPF_F_ANY_ALIGNMENT)
148 __naked void regalloc_and_spill(void)
153 *(u64*)(r10 - 8) = r1; \
156 r1 = %[map_hash_48b] ll; \
157 call %[bpf_map_lookup_elem]; \
158 if r0 == 0 goto l0_%=; \
160 call %[bpf_get_prandom_u32]; \
162 if r0 s> 20 goto l0_%=; \
163 /* r0 has upper bound that should propagate into r2 */\
164 *(u64*)(r10 - 8) = r2; /* spill r2 */ \
166 r2 = 0; /* clear r0 and r2 */\
167 r3 = *(u64*)(r10 - 8); /* fill r3 */ \
168 if r0 s>= r3 goto l0_%=; \
169 /* r3 has lower and upper bounds */ \
171 r0 = *(u64*)(r7 + 0); \
174 : __imm(bpf_get_prandom_u32),
175 __imm(bpf_map_lookup_elem),
176 __imm_addr(map_hash_48b)
181 __description("regalloc and spill negative")
182 __failure __msg("invalid access to map value, value_size=48 off=48 size=8")
183 __flag(BPF_F_ANY_ALIGNMENT)
184 __naked void regalloc_and_spill_negative(void)
189 *(u64*)(r10 - 8) = r1; \
192 r1 = %[map_hash_48b] ll; \
193 call %[bpf_map_lookup_elem]; \
194 if r0 == 0 goto l0_%=; \
196 call %[bpf_get_prandom_u32]; \
198 if r0 s> 48 goto l0_%=; \
199 /* r0 has upper bound that should propagate into r2 */\
200 *(u64*)(r10 - 8) = r2; /* spill r2 */ \
202 r2 = 0; /* clear r0 and r2 */\
203 r3 = *(u64*)(r10 - 8); /* fill r3 */\
204 if r0 s>= r3 goto l0_%=; \
205 /* r3 has lower and upper bounds */ \
207 r0 = *(u64*)(r7 + 0); \
210 : __imm(bpf_get_prandom_u32),
211 __imm(bpf_map_lookup_elem),
212 __imm_addr(map_hash_48b)
217 __description("regalloc three regs")
218 __success __flag(BPF_F_ANY_ALIGNMENT)
219 __naked void regalloc_three_regs(void)
224 *(u64*)(r10 - 8) = r1; \
227 r1 = %[map_hash_48b] ll; \
228 call %[bpf_map_lookup_elem]; \
229 if r0 == 0 goto l0_%=; \
231 call %[bpf_get_prandom_u32]; \
234 if r0 s> 12 goto l0_%=; \
235 if r2 s< 0 goto l0_%=; \
239 r0 = *(u64*)(r7 + 0); \
242 : __imm(bpf_get_prandom_u32),
243 __imm(bpf_map_lookup_elem),
244 __imm_addr(map_hash_48b)
249 __description("regalloc after call")
250 __success __flag(BPF_F_ANY_ALIGNMENT)
251 __naked void regalloc_after_call(void)
256 *(u64*)(r10 - 8) = r1; \
259 r1 = %[map_hash_48b] ll; \
260 call %[bpf_map_lookup_elem]; \
261 if r0 == 0 goto l0_%=; \
263 call %[bpf_get_prandom_u32]; \
266 call regalloc_after_call__1; \
267 if r8 s> 20 goto l0_%=; \
268 if r9 s< 0 goto l0_%=; \
271 r0 = *(u64*)(r7 + 0); \
274 : __imm(bpf_get_prandom_u32),
275 __imm(bpf_map_lookup_elem),
276 __imm_addr(map_hash_48b)
280 static __naked __noinline __attribute__((used))
281 void regalloc_after_call__1(void)
286 " ::: __clobber_all);
290 __description("regalloc in callee")
291 __success __flag(BPF_F_ANY_ALIGNMENT)
292 __naked void regalloc_in_callee(void)
297 *(u64*)(r10 - 8) = r1; \
300 r1 = %[map_hash_48b] ll; \
301 call %[bpf_map_lookup_elem]; \
302 if r0 == 0 goto l0_%=; \
304 call %[bpf_get_prandom_u32]; \
308 call regalloc_in_callee__1; \
311 : __imm(bpf_get_prandom_u32),
312 __imm(bpf_map_lookup_elem),
313 __imm_addr(map_hash_48b)
317 static __naked __noinline __attribute__((used))
318 void regalloc_in_callee__1(void)
321 if r1 s> 20 goto l0_%=; \
322 if r2 s< 0 goto l0_%=; \
325 r0 = *(u64*)(r3 + 0); \
329 " ::: __clobber_all);
333 __description("regalloc, spill, JEQ")
335 __naked void regalloc_spill_jeq(void)
340 *(u64*)(r10 - 8) = r1; \
343 r1 = %[map_hash_48b] ll; \
344 call %[bpf_map_lookup_elem]; \
345 *(u64*)(r10 - 8) = r0; /* spill r0 */ \
346 if r0 == 0 goto l0_%=; \
347 l0_%=: /* The verifier will walk the rest twice with r0 == 0 and r0 == map_value */\
348 call %[bpf_get_prandom_u32]; \
350 if r2 == 20 goto l1_%=; \
351 l1_%=: /* The verifier will walk the rest two more times with r0 == 20 and r0 == unknown */\
352 r3 = *(u64*)(r10 - 8); /* fill r3 with map_value */\
353 if r3 == 0 goto l2_%=; /* skip ldx if map_value == NULL */\
354 /* Buggy verifier will think that r3 == 20 here */\
355 r0 = *(u64*)(r3 + 0); /* read from map_value */\
358 : __imm(bpf_get_prandom_u32),
359 __imm(bpf_map_lookup_elem),
360 __imm_addr(map_hash_48b)
364 char _license[] SEC("license") = "GPL";