1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/stack_ptr.c */
5 #include <bpf/bpf_helpers.h>
17 __uint(type, BPF_MAP_TYPE_ARRAY);
18 __uint(max_entries, 1);
20 __type(value, struct test_val);
21 } map_array_48b SEC(".maps");
24 __description("PTR_TO_STACK store/load")
25 __success __success_unpriv __retval(0xfaceb00c)
26 __naked void ptr_to_stack_store_load(void)
32 *(u64*)(r1 + 2) = r0; \
33 r0 = *(u64*)(r1 + 2); \
39 __description("PTR_TO_STACK store/load - bad alignment on off")
40 __failure __msg("misaligned stack access off 0+-8+2 size 8")
42 __naked void load_bad_alignment_on_off(void)
48 *(u64*)(r1 + 2) = r0; \
49 r0 = *(u64*)(r1 + 2); \
55 __description("PTR_TO_STACK store/load - bad alignment on reg")
56 __failure __msg("misaligned stack access off 0+-10+8 size 8")
58 __naked void load_bad_alignment_on_reg(void)
64 *(u64*)(r1 + 8) = r0; \
65 r0 = *(u64*)(r1 + 8); \
71 __description("PTR_TO_STACK store/load - out of bounds low")
72 __failure __msg("invalid write to stack R1 off=-79992 size=8")
73 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
74 __naked void load_out_of_bounds_low(void)
80 *(u64*)(r1 + 8) = r0; \
81 r0 = *(u64*)(r1 + 8); \
87 __description("PTR_TO_STACK store/load - out of bounds high")
88 __failure __msg("invalid write to stack R1 off=0 size=8")
90 __naked void load_out_of_bounds_high(void)
96 *(u64*)(r1 + 8) = r0; \
97 r0 = *(u64*)(r1 + 8); \
103 __description("PTR_TO_STACK check high 1")
104 __success __success_unpriv __retval(42)
105 __naked void to_stack_check_high_1(void)
111 *(u8*)(r1 + 0) = r0; \
112 r0 = *(u8*)(r1 + 0); \
114 " ::: __clobber_all);
118 __description("PTR_TO_STACK check high 2")
119 __success __success_unpriv __retval(42)
120 __naked void to_stack_check_high_2(void)
125 *(u8*)(r1 - 1) = r0; \
126 r0 = *(u8*)(r1 - 1); \
128 " ::: __clobber_all);
132 __description("PTR_TO_STACK check high 3")
133 __success __failure_unpriv
134 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
136 __naked void to_stack_check_high_3(void)
142 *(u8*)(r1 - 1) = r0; \
143 r0 = *(u8*)(r1 - 1); \
145 " ::: __clobber_all);
149 __description("PTR_TO_STACK check high 4")
150 __failure __msg("invalid write to stack R1 off=0 size=1")
151 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
152 __naked void to_stack_check_high_4(void)
158 *(u8*)(r1 + 0) = r0; \
159 r0 = *(u8*)(r1 + 0); \
161 " ::: __clobber_all);
165 __description("PTR_TO_STACK check high 5")
166 __failure __msg("invalid write to stack R1")
167 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
168 __naked void to_stack_check_high_5(void)
174 *(u8*)(r1 + 0) = r0; \
175 r0 = *(u8*)(r1 + 0); \
178 : __imm_const(__imm_0, (1 << 29) - 1)
183 __description("PTR_TO_STACK check high 6")
184 __failure __msg("invalid write to stack")
185 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
186 __naked void to_stack_check_high_6(void)
192 *(u8*)(r1 + %[shrt_max]) = r0; \
193 r0 = *(u8*)(r1 + %[shrt_max]); \
196 : __imm_const(__imm_0, (1 << 29) - 1),
197 __imm_const(shrt_max, SHRT_MAX)
202 __description("PTR_TO_STACK check high 7")
203 __failure __msg("fp pointer offset")
204 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
205 __naked void to_stack_check_high_7(void)
212 *(u8*)(r1 + %[shrt_max]) = r0; \
213 r0 = *(u8*)(r1 + %[shrt_max]); \
216 : __imm_const(__imm_0, (1 << 29) - 1),
217 __imm_const(shrt_max, SHRT_MAX)
222 __description("PTR_TO_STACK check low 1")
223 __success __success_unpriv __retval(42)
224 __naked void to_stack_check_low_1(void)
230 *(u8*)(r1 + 0) = r0; \
231 r0 = *(u8*)(r1 + 0); \
233 " ::: __clobber_all);
237 __description("PTR_TO_STACK check low 2")
238 __success __failure_unpriv
239 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
241 __naked void to_stack_check_low_2(void)
247 *(u8*)(r1 + 1) = r0; \
248 r0 = *(u8*)(r1 + 1); \
250 " ::: __clobber_all);
254 __description("PTR_TO_STACK check low 3")
255 __failure __msg("invalid write to stack R1 off=-513 size=1")
256 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
257 __naked void to_stack_check_low_3(void)
263 *(u8*)(r1 + 0) = r0; \
264 r0 = *(u8*)(r1 + 0); \
266 " ::: __clobber_all);
270 __description("PTR_TO_STACK check low 4")
271 __failure __msg("math between fp pointer")
273 __naked void to_stack_check_low_4(void)
279 *(u8*)(r1 + 0) = r0; \
280 r0 = *(u8*)(r1 + 0); \
283 : __imm_const(int_min, INT_MIN)
288 __description("PTR_TO_STACK check low 5")
289 __failure __msg("invalid write to stack")
290 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
291 __naked void to_stack_check_low_5(void)
297 *(u8*)(r1 + 0) = r0; \
298 r0 = *(u8*)(r1 + 0); \
301 : __imm_const(__imm_0, -((1 << 29) - 1))
306 __description("PTR_TO_STACK check low 6")
307 __failure __msg("invalid write to stack")
308 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
309 __naked void to_stack_check_low_6(void)
315 *(u8*)(r1 %[shrt_min]) = r0; \
316 r0 = *(u8*)(r1 %[shrt_min]); \
319 : __imm_const(__imm_0, -((1 << 29) - 1)),
320 __imm_const(shrt_min, SHRT_MIN)
325 __description("PTR_TO_STACK check low 7")
326 __failure __msg("fp pointer offset")
327 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
328 __naked void to_stack_check_low_7(void)
335 *(u8*)(r1 %[shrt_min]) = r0; \
336 r0 = *(u8*)(r1 %[shrt_min]); \
339 : __imm_const(__imm_0, -((1 << 29) - 1)),
340 __imm_const(shrt_min, SHRT_MIN)
345 __description("PTR_TO_STACK mixed reg/k, 1")
346 __success __success_unpriv __retval(42)
347 __naked void stack_mixed_reg_k_1(void)
355 *(u8*)(r1 + 0) = r0; \
356 r0 = *(u8*)(r1 + 0); \
358 " ::: __clobber_all);
362 __description("PTR_TO_STACK mixed reg/k, 2")
363 __success __success_unpriv __retval(42)
364 __naked void stack_mixed_reg_k_2(void)
368 *(u64*)(r10 - 8) = r0; \
370 *(u64*)(r10 - 16) = r0; \
376 *(u8*)(r1 + 0) = r0; \
378 r0 = *(u8*)(r5 - 6); \
380 " ::: __clobber_all);
384 __description("PTR_TO_STACK mixed reg/k, 3")
385 __success __success_unpriv __retval(-3)
386 __naked void stack_mixed_reg_k_3(void)
394 *(u8*)(r1 + 0) = r0; \
397 " ::: __clobber_all);
401 __description("PTR_TO_STACK reg")
402 __success __success_unpriv __retval(42)
403 __naked void ptr_to_stack_reg(void)
410 *(u8*)(r1 + 0) = r0; \
411 r0 = *(u8*)(r1 + 0); \
413 " ::: __clobber_all);
417 __description("stack pointer arithmetic")
418 __success __success_unpriv __retval(0)
419 __naked void stack_pointer_arithmetic(void)
430 *(u32*)(r2 + 4) = r0; \
434 *(u32*)(r2 + 4) = r0; \
437 " ::: __clobber_all);
441 __description("store PTR_TO_STACK in R10 to array map using BPF_B")
442 __success __retval(42)
443 __naked void array_map_using_bpf_b(void)
446 /* Load pointer to map. */ \
450 *(u64*)(r2 + 0) = r1; \
451 r1 = %[map_array_48b] ll; \
452 call %[bpf_map_lookup_elem]; \
453 if r0 != 0 goto l0_%=; \
457 /* Copy R10 to R9. */ \
459 /* Pollute other registers with unaligned values. */\
467 /* Store both R9 and R10 with BPF_B and read back. */\
468 *(u8*)(r1 + 0) = r10; \
469 r2 = *(u8*)(r1 + 0); \
470 *(u8*)(r1 + 0) = r9; \
471 r3 = *(u8*)(r1 + 0); \
472 /* Should read back as same value. */ \
473 if r2 == r3 goto l1_%=; \
479 : __imm(bpf_map_lookup_elem),
480 __imm_addr(map_array_48b)
484 char _license[] SEC("license") = "GPL";