]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/progs/verifier_stack_ptr.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / progs / verifier_stack_ptr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/stack_ptr.c */
3
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include <limits.h>
7 #include "bpf_misc.h"
8
9 #define MAX_ENTRIES 11
10
11 struct test_val {
12         unsigned int index;
13         int foo[MAX_ENTRIES];
14 };
15
16 struct {
17         __uint(type, BPF_MAP_TYPE_ARRAY);
18         __uint(max_entries, 1);
19         __type(key, int);
20         __type(value, struct test_val);
21 } map_array_48b SEC(".maps");
22
23 SEC("socket")
24 __description("PTR_TO_STACK store/load")
25 __success __success_unpriv __retval(0xfaceb00c)
26 __naked void ptr_to_stack_store_load(void)
27 {
28         asm volatile ("                                 \
29         r1 = r10;                                       \
30         r1 += -10;                                      \
31         r0 = 0xfaceb00c;                                \
32         *(u64*)(r1 + 2) = r0;                           \
33         r0 = *(u64*)(r1 + 2);                           \
34         exit;                                           \
35 "       ::: __clobber_all);
36 }
37
38 SEC("socket")
39 __description("PTR_TO_STACK store/load - bad alignment on off")
40 __failure __msg("misaligned stack access off 0+-8+2 size 8")
41 __failure_unpriv
42 __naked void load_bad_alignment_on_off(void)
43 {
44         asm volatile ("                                 \
45         r1 = r10;                                       \
46         r1 += -8;                                       \
47         r0 = 0xfaceb00c;                                \
48         *(u64*)(r1 + 2) = r0;                           \
49         r0 = *(u64*)(r1 + 2);                           \
50         exit;                                           \
51 "       ::: __clobber_all);
52 }
53
54 SEC("socket")
55 __description("PTR_TO_STACK store/load - bad alignment on reg")
56 __failure __msg("misaligned stack access off 0+-10+8 size 8")
57 __failure_unpriv
58 __naked void load_bad_alignment_on_reg(void)
59 {
60         asm volatile ("                                 \
61         r1 = r10;                                       \
62         r1 += -10;                                      \
63         r0 = 0xfaceb00c;                                \
64         *(u64*)(r1 + 8) = r0;                           \
65         r0 = *(u64*)(r1 + 8);                           \
66         exit;                                           \
67 "       ::: __clobber_all);
68 }
69
70 SEC("socket")
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)
75 {
76         asm volatile ("                                 \
77         r1 = r10;                                       \
78         r1 += -80000;                                   \
79         r0 = 0xfaceb00c;                                \
80         *(u64*)(r1 + 8) = r0;                           \
81         r0 = *(u64*)(r1 + 8);                           \
82         exit;                                           \
83 "       ::: __clobber_all);
84 }
85
86 SEC("socket")
87 __description("PTR_TO_STACK store/load - out of bounds high")
88 __failure __msg("invalid write to stack R1 off=0 size=8")
89 __failure_unpriv
90 __naked void load_out_of_bounds_high(void)
91 {
92         asm volatile ("                                 \
93         r1 = r10;                                       \
94         r1 += -8;                                       \
95         r0 = 0xfaceb00c;                                \
96         *(u64*)(r1 + 8) = r0;                           \
97         r0 = *(u64*)(r1 + 8);                           \
98         exit;                                           \
99 "       ::: __clobber_all);
100 }
101
102 SEC("socket")
103 __description("PTR_TO_STACK check high 1")
104 __success __success_unpriv __retval(42)
105 __naked void to_stack_check_high_1(void)
106 {
107         asm volatile ("                                 \
108         r1 = r10;                                       \
109         r1 += -1;                                       \
110         r0 = 42;                                        \
111         *(u8*)(r1 + 0) = r0;                            \
112         r0 = *(u8*)(r1 + 0);                            \
113         exit;                                           \
114 "       ::: __clobber_all);
115 }
116
117 SEC("socket")
118 __description("PTR_TO_STACK check high 2")
119 __success __success_unpriv __retval(42)
120 __naked void to_stack_check_high_2(void)
121 {
122         asm volatile ("                                 \
123         r1 = r10;                                       \
124         r0 = 42;                                        \
125         *(u8*)(r1 - 1) = r0;                            \
126         r0 = *(u8*)(r1 - 1);                            \
127         exit;                                           \
128 "       ::: __clobber_all);
129 }
130
131 SEC("socket")
132 __description("PTR_TO_STACK check high 3")
133 __success __failure_unpriv
134 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
135 __retval(42)
136 __naked void to_stack_check_high_3(void)
137 {
138         asm volatile ("                                 \
139         r1 = r10;                                       \
140         r1 += 0;                                        \
141         r0 = 42;                                        \
142         *(u8*)(r1 - 1) = r0;                            \
143         r0 = *(u8*)(r1 - 1);                            \
144         exit;                                           \
145 "       ::: __clobber_all);
146 }
147
148 SEC("socket")
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)
153 {
154         asm volatile ("                                 \
155         r1 = r10;                                       \
156         r1 += 0;                                        \
157         r0 = 42;                                        \
158         *(u8*)(r1 + 0) = r0;                            \
159         r0 = *(u8*)(r1 + 0);                            \
160         exit;                                           \
161 "       ::: __clobber_all);
162 }
163
164 SEC("socket")
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)
169 {
170         asm volatile ("                                 \
171         r1 = r10;                                       \
172         r1 += %[__imm_0];                               \
173         r0 = 42;                                        \
174         *(u8*)(r1 + 0) = r0;                            \
175         r0 = *(u8*)(r1 + 0);                            \
176         exit;                                           \
177 "       :
178         : __imm_const(__imm_0, (1 << 29) - 1)
179         : __clobber_all);
180 }
181
182 SEC("socket")
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)
187 {
188         asm volatile ("                                 \
189         r1 = r10;                                       \
190         r1 += %[__imm_0];                               \
191         r0 = 42;                                        \
192         *(u8*)(r1 + %[shrt_max]) = r0;                  \
193         r0 = *(u8*)(r1 + %[shrt_max]);                  \
194         exit;                                           \
195 "       :
196         : __imm_const(__imm_0, (1 << 29) - 1),
197           __imm_const(shrt_max, SHRT_MAX)
198         : __clobber_all);
199 }
200
201 SEC("socket")
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)
206 {
207         asm volatile ("                                 \
208         r1 = r10;                                       \
209         r1 += %[__imm_0];                               \
210         r1 += %[__imm_0];                               \
211         r0 = 42;                                        \
212         *(u8*)(r1 + %[shrt_max]) = r0;                  \
213         r0 = *(u8*)(r1 + %[shrt_max]);                  \
214         exit;                                           \
215 "       :
216         : __imm_const(__imm_0, (1 << 29) - 1),
217           __imm_const(shrt_max, SHRT_MAX)
218         : __clobber_all);
219 }
220
221 SEC("socket")
222 __description("PTR_TO_STACK check low 1")
223 __success __success_unpriv __retval(42)
224 __naked void to_stack_check_low_1(void)
225 {
226         asm volatile ("                                 \
227         r1 = r10;                                       \
228         r1 += -512;                                     \
229         r0 = 42;                                        \
230         *(u8*)(r1 + 0) = r0;                            \
231         r0 = *(u8*)(r1 + 0);                            \
232         exit;                                           \
233 "       ::: __clobber_all);
234 }
235
236 SEC("socket")
237 __description("PTR_TO_STACK check low 2")
238 __success __failure_unpriv
239 __msg_unpriv("R1 stack pointer arithmetic goes out of range")
240 __retval(42)
241 __naked void to_stack_check_low_2(void)
242 {
243         asm volatile ("                                 \
244         r1 = r10;                                       \
245         r1 += -513;                                     \
246         r0 = 42;                                        \
247         *(u8*)(r1 + 1) = r0;                            \
248         r0 = *(u8*)(r1 + 1);                            \
249         exit;                                           \
250 "       ::: __clobber_all);
251 }
252
253 SEC("socket")
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)
258 {
259         asm volatile ("                                 \
260         r1 = r10;                                       \
261         r1 += -513;                                     \
262         r0 = 42;                                        \
263         *(u8*)(r1 + 0) = r0;                            \
264         r0 = *(u8*)(r1 + 0);                            \
265         exit;                                           \
266 "       ::: __clobber_all);
267 }
268
269 SEC("socket")
270 __description("PTR_TO_STACK check low 4")
271 __failure __msg("math between fp pointer")
272 __failure_unpriv
273 __naked void to_stack_check_low_4(void)
274 {
275         asm volatile ("                                 \
276         r1 = r10;                                       \
277         r1 += %[int_min];                               \
278         r0 = 42;                                        \
279         *(u8*)(r1 + 0) = r0;                            \
280         r0 = *(u8*)(r1 + 0);                            \
281         exit;                                           \
282 "       :
283         : __imm_const(int_min, INT_MIN)
284         : __clobber_all);
285 }
286
287 SEC("socket")
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)
292 {
293         asm volatile ("                                 \
294         r1 = r10;                                       \
295         r1 += %[__imm_0];                               \
296         r0 = 42;                                        \
297         *(u8*)(r1 + 0) = r0;                            \
298         r0 = *(u8*)(r1 + 0);                            \
299         exit;                                           \
300 "       :
301         : __imm_const(__imm_0, -((1 << 29) - 1))
302         : __clobber_all);
303 }
304
305 SEC("socket")
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)
310 {
311         asm volatile ("                                 \
312         r1 = r10;                                       \
313         r1 += %[__imm_0];                               \
314         r0 = 42;                                        \
315         *(u8*)(r1  %[shrt_min]) = r0;                   \
316         r0 = *(u8*)(r1  %[shrt_min]);                   \
317         exit;                                           \
318 "       :
319         : __imm_const(__imm_0, -((1 << 29) - 1)),
320           __imm_const(shrt_min, SHRT_MIN)
321         : __clobber_all);
322 }
323
324 SEC("socket")
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)
329 {
330         asm volatile ("                                 \
331         r1 = r10;                                       \
332         r1 += %[__imm_0];                               \
333         r1 += %[__imm_0];                               \
334         r0 = 42;                                        \
335         *(u8*)(r1  %[shrt_min]) = r0;                   \
336         r0 = *(u8*)(r1  %[shrt_min]);                   \
337         exit;                                           \
338 "       :
339         : __imm_const(__imm_0, -((1 << 29) - 1)),
340           __imm_const(shrt_min, SHRT_MIN)
341         : __clobber_all);
342 }
343
344 SEC("socket")
345 __description("PTR_TO_STACK mixed reg/k, 1")
346 __success __success_unpriv __retval(42)
347 __naked void stack_mixed_reg_k_1(void)
348 {
349         asm volatile ("                                 \
350         r1 = r10;                                       \
351         r1 += -3;                                       \
352         r2 = -3;                                        \
353         r1 += r2;                                       \
354         r0 = 42;                                        \
355         *(u8*)(r1 + 0) = r0;                            \
356         r0 = *(u8*)(r1 + 0);                            \
357         exit;                                           \
358 "       ::: __clobber_all);
359 }
360
361 SEC("socket")
362 __description("PTR_TO_STACK mixed reg/k, 2")
363 __success __success_unpriv __retval(42)
364 __naked void stack_mixed_reg_k_2(void)
365 {
366         asm volatile ("                                 \
367         r0 = 0;                                         \
368         *(u64*)(r10 - 8) = r0;                          \
369         r0 = 0;                                         \
370         *(u64*)(r10 - 16) = r0;                         \
371         r1 = r10;                                       \
372         r1 += -3;                                       \
373         r2 = -3;                                        \
374         r1 += r2;                                       \
375         r0 = 42;                                        \
376         *(u8*)(r1 + 0) = r0;                            \
377         r5 = r10;                                       \
378         r0 = *(u8*)(r5 - 6);                            \
379         exit;                                           \
380 "       ::: __clobber_all);
381 }
382
383 SEC("socket")
384 __description("PTR_TO_STACK mixed reg/k, 3")
385 __success __success_unpriv __retval(-3)
386 __naked void stack_mixed_reg_k_3(void)
387 {
388         asm volatile ("                                 \
389         r1 = r10;                                       \
390         r1 += -3;                                       \
391         r2 = -3;                                        \
392         r1 += r2;                                       \
393         r0 = 42;                                        \
394         *(u8*)(r1 + 0) = r0;                            \
395         r0 = r2;                                        \
396         exit;                                           \
397 "       ::: __clobber_all);
398 }
399
400 SEC("socket")
401 __description("PTR_TO_STACK reg")
402 __success __success_unpriv __retval(42)
403 __naked void ptr_to_stack_reg(void)
404 {
405         asm volatile ("                                 \
406         r1 = r10;                                       \
407         r2 = -3;                                        \
408         r1 += r2;                                       \
409         r0 = 42;                                        \
410         *(u8*)(r1 + 0) = r0;                            \
411         r0 = *(u8*)(r1 + 0);                            \
412         exit;                                           \
413 "       ::: __clobber_all);
414 }
415
416 SEC("socket")
417 __description("stack pointer arithmetic")
418 __success __success_unpriv __retval(0)
419 __naked void stack_pointer_arithmetic(void)
420 {
421         asm volatile ("                                 \
422         r1 = 4;                                         \
423         goto l0_%=;                                     \
424 l0_%=:  r7 = r10;                                       \
425         r7 += -10;                                      \
426         r7 += -10;                                      \
427         r2 = r7;                                        \
428         r2 += r1;                                       \
429         r0 = 0;                                         \
430         *(u32*)(r2 + 4) = r0;                           \
431         r2 = r7;                                        \
432         r2 += 8;                                        \
433         r0 = 0;                                         \
434         *(u32*)(r2 + 4) = r0;                           \
435         r0 = 0;                                         \
436         exit;                                           \
437 "       ::: __clobber_all);
438 }
439
440 SEC("tc")
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)
444 {
445         asm volatile ("                                 \
446         /* Load pointer to map. */                      \
447         r2 = r10;                                       \
448         r2 += -8;                                       \
449         r1 = 0;                                         \
450         *(u64*)(r2 + 0) = r1;                           \
451         r1 = %[map_array_48b] ll;                       \
452         call %[bpf_map_lookup_elem];                    \
453         if r0 != 0 goto l0_%=;                          \
454         r0 = 2;                                         \
455         exit;                                           \
456 l0_%=:  r1 = r0;                                        \
457         /* Copy R10 to R9. */                           \
458         r9 = r10;                                       \
459         /* Pollute other registers with unaligned values. */\
460         r2 = -1;                                        \
461         r3 = -1;                                        \
462         r4 = -1;                                        \
463         r5 = -1;                                        \
464         r6 = -1;                                        \
465         r7 = -1;                                        \
466         r8 = -1;                                        \
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_%=;                         \
474         r0 = 1;                                         \
475         exit;                                           \
476 l1_%=:  r0 = 42;                                        \
477         exit;                                           \
478 "       :
479         : __imm(bpf_map_lookup_elem),
480           __imm_addr(map_array_48b)
481         : __clobber_all);
482 }
483
484 char _license[] SEC("license") = "GPL";
This page took 0.062128 seconds and 4 git commands to generate.