]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/progs/verifier_runtime_jit.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / progs / verifier_runtime_jit.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/runtime_jit.c */
3
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7
8 void dummy_prog_42_socket(void);
9 void dummy_prog_24_socket(void);
10 void dummy_prog_loop1_socket(void);
11 void dummy_prog_loop2_socket(void);
12
13 struct {
14         __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
15         __uint(max_entries, 4);
16         __uint(key_size, sizeof(int));
17         __array(values, void (void));
18 } map_prog1_socket SEC(".maps") = {
19         .values = {
20                 [0] = (void *)&dummy_prog_42_socket,
21                 [1] = (void *)&dummy_prog_loop1_socket,
22                 [2] = (void *)&dummy_prog_24_socket,
23         },
24 };
25
26 struct {
27         __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
28         __uint(max_entries, 8);
29         __uint(key_size, sizeof(int));
30         __array(values, void (void));
31 } map_prog2_socket SEC(".maps") = {
32         .values = {
33                 [1] = (void *)&dummy_prog_loop2_socket,
34                 [2] = (void *)&dummy_prog_24_socket,
35                 [7] = (void *)&dummy_prog_42_socket,
36         },
37 };
38
39 SEC("socket")
40 __auxiliary __auxiliary_unpriv
41 __naked void dummy_prog_42_socket(void)
42 {
43         asm volatile ("r0 = 42; exit;");
44 }
45
46 SEC("socket")
47 __auxiliary __auxiliary_unpriv
48 __naked void dummy_prog_24_socket(void)
49 {
50         asm volatile ("r0 = 24; exit;");
51 }
52
53 SEC("socket")
54 __auxiliary __auxiliary_unpriv
55 __naked void dummy_prog_loop1_socket(void)
56 {
57         asm volatile ("                 \
58         r3 = 1;                         \
59         r2 = %[map_prog1_socket] ll;    \
60         call %[bpf_tail_call];          \
61         r0 = 41;                        \
62         exit;                           \
63 "       :
64         : __imm(bpf_tail_call),
65           __imm_addr(map_prog1_socket)
66         : __clobber_all);
67 }
68
69 SEC("socket")
70 __auxiliary __auxiliary_unpriv
71 __naked void dummy_prog_loop2_socket(void)
72 {
73         asm volatile ("                 \
74         r3 = 1;                         \
75         r2 = %[map_prog2_socket] ll;    \
76         call %[bpf_tail_call];          \
77         r0 = 41;                        \
78         exit;                           \
79 "       :
80         : __imm(bpf_tail_call),
81           __imm_addr(map_prog2_socket)
82         : __clobber_all);
83 }
84
85 SEC("socket")
86 __description("runtime/jit: tail_call within bounds, prog once")
87 __success __success_unpriv __retval(42)
88 __naked void call_within_bounds_prog_once(void)
89 {
90         asm volatile ("                                 \
91         r3 = 0;                                         \
92         r2 = %[map_prog1_socket] ll;                    \
93         call %[bpf_tail_call];                          \
94         r0 = 1;                                         \
95         exit;                                           \
96 "       :
97         : __imm(bpf_tail_call),
98           __imm_addr(map_prog1_socket)
99         : __clobber_all);
100 }
101
102 SEC("socket")
103 __description("runtime/jit: tail_call within bounds, prog loop")
104 __success __success_unpriv __retval(41)
105 __naked void call_within_bounds_prog_loop(void)
106 {
107         asm volatile ("                                 \
108         r3 = 1;                                         \
109         r2 = %[map_prog1_socket] ll;                    \
110         call %[bpf_tail_call];                          \
111         r0 = 1;                                         \
112         exit;                                           \
113 "       :
114         : __imm(bpf_tail_call),
115           __imm_addr(map_prog1_socket)
116         : __clobber_all);
117 }
118
119 SEC("socket")
120 __description("runtime/jit: tail_call within bounds, no prog")
121 __success __success_unpriv __retval(1)
122 __naked void call_within_bounds_no_prog(void)
123 {
124         asm volatile ("                                 \
125         r3 = 3;                                         \
126         r2 = %[map_prog1_socket] ll;                    \
127         call %[bpf_tail_call];                          \
128         r0 = 1;                                         \
129         exit;                                           \
130 "       :
131         : __imm(bpf_tail_call),
132           __imm_addr(map_prog1_socket)
133         : __clobber_all);
134 }
135
136 SEC("socket")
137 __description("runtime/jit: tail_call within bounds, key 2")
138 __success __success_unpriv __retval(24)
139 __naked void call_within_bounds_key_2(void)
140 {
141         asm volatile ("                                 \
142         r3 = 2;                                         \
143         r2 = %[map_prog1_socket] ll;                    \
144         call %[bpf_tail_call];                          \
145         r0 = 1;                                         \
146         exit;                                           \
147 "       :
148         : __imm(bpf_tail_call),
149           __imm_addr(map_prog1_socket)
150         : __clobber_all);
151 }
152
153 SEC("socket")
154 __description("runtime/jit: tail_call within bounds, key 2 / key 2, first branch")
155 __success __success_unpriv __retval(24)
156 __naked void _2_key_2_first_branch(void)
157 {
158         asm volatile ("                                 \
159         r0 = 13;                                        \
160         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
161         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
162         if r0 == 13 goto l0_%=;                         \
163         r3 = 2;                                         \
164         r2 = %[map_prog1_socket] ll;                    \
165         goto l1_%=;                                     \
166 l0_%=:  r3 = 2;                                         \
167         r2 = %[map_prog1_socket] ll;                    \
168 l1_%=:  call %[bpf_tail_call];                          \
169         r0 = 1;                                         \
170         exit;                                           \
171 "       :
172         : __imm(bpf_tail_call),
173           __imm_addr(map_prog1_socket),
174           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
175         : __clobber_all);
176 }
177
178 SEC("socket")
179 __description("runtime/jit: tail_call within bounds, key 2 / key 2, second branch")
180 __success __success_unpriv __retval(24)
181 __naked void _2_key_2_second_branch(void)
182 {
183         asm volatile ("                                 \
184         r0 = 14;                                        \
185         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
186         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
187         if r0 == 13 goto l0_%=;                         \
188         r3 = 2;                                         \
189         r2 = %[map_prog1_socket] ll;                    \
190         goto l1_%=;                                     \
191 l0_%=:  r3 = 2;                                         \
192         r2 = %[map_prog1_socket] ll;                    \
193 l1_%=:  call %[bpf_tail_call];                          \
194         r0 = 1;                                         \
195         exit;                                           \
196 "       :
197         : __imm(bpf_tail_call),
198           __imm_addr(map_prog1_socket),
199           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
200         : __clobber_all);
201 }
202
203 SEC("socket")
204 __description("runtime/jit: tail_call within bounds, key 0 / key 2, first branch")
205 __success __success_unpriv __retval(24)
206 __naked void _0_key_2_first_branch(void)
207 {
208         asm volatile ("                                 \
209         r0 = 13;                                        \
210         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
211         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
212         if r0 == 13 goto l0_%=;                         \
213         r3 = 0;                                         \
214         r2 = %[map_prog1_socket] ll;                    \
215         goto l1_%=;                                     \
216 l0_%=:  r3 = 2;                                         \
217         r2 = %[map_prog1_socket] ll;                    \
218 l1_%=:  call %[bpf_tail_call];                          \
219         r0 = 1;                                         \
220         exit;                                           \
221 "       :
222         : __imm(bpf_tail_call),
223           __imm_addr(map_prog1_socket),
224           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
225         : __clobber_all);
226 }
227
228 SEC("socket")
229 __description("runtime/jit: tail_call within bounds, key 0 / key 2, second branch")
230 __success __success_unpriv __retval(42)
231 __naked void _0_key_2_second_branch(void)
232 {
233         asm volatile ("                                 \
234         r0 = 14;                                        \
235         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
236         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
237         if r0 == 13 goto l0_%=;                         \
238         r3 = 0;                                         \
239         r2 = %[map_prog1_socket] ll;                    \
240         goto l1_%=;                                     \
241 l0_%=:  r3 = 2;                                         \
242         r2 = %[map_prog1_socket] ll;                    \
243 l1_%=:  call %[bpf_tail_call];                          \
244         r0 = 1;                                         \
245         exit;                                           \
246 "       :
247         : __imm(bpf_tail_call),
248           __imm_addr(map_prog1_socket),
249           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
250         : __clobber_all);
251 }
252
253 SEC("socket")
254 __description("runtime/jit: tail_call within bounds, different maps, first branch")
255 __success __failure_unpriv __msg_unpriv("tail_call abusing map_ptr")
256 __retval(1)
257 __naked void bounds_different_maps_first_branch(void)
258 {
259         asm volatile ("                                 \
260         r0 = 13;                                        \
261         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
262         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
263         if r0 == 13 goto l0_%=;                         \
264         r3 = 0;                                         \
265         r2 = %[map_prog1_socket] ll;                    \
266         goto l1_%=;                                     \
267 l0_%=:  r3 = 0;                                         \
268         r2 = %[map_prog2_socket] ll;                    \
269 l1_%=:  call %[bpf_tail_call];                          \
270         r0 = 1;                                         \
271         exit;                                           \
272 "       :
273         : __imm(bpf_tail_call),
274           __imm_addr(map_prog1_socket),
275           __imm_addr(map_prog2_socket),
276           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
277         : __clobber_all);
278 }
279
280 SEC("socket")
281 __description("runtime/jit: tail_call within bounds, different maps, second branch")
282 __success __failure_unpriv __msg_unpriv("tail_call abusing map_ptr")
283 __retval(42)
284 __naked void bounds_different_maps_second_branch(void)
285 {
286         asm volatile ("                                 \
287         r0 = 14;                                        \
288         *(u8*)(r1 + %[__sk_buff_cb_0]) = r0;            \
289         r0 = *(u8*)(r1 + %[__sk_buff_cb_0]);            \
290         if r0 == 13 goto l0_%=;                         \
291         r3 = 0;                                         \
292         r2 = %[map_prog1_socket] ll;                    \
293         goto l1_%=;                                     \
294 l0_%=:  r3 = 0;                                         \
295         r2 = %[map_prog2_socket] ll;                    \
296 l1_%=:  call %[bpf_tail_call];                          \
297         r0 = 1;                                         \
298         exit;                                           \
299 "       :
300         : __imm(bpf_tail_call),
301           __imm_addr(map_prog1_socket),
302           __imm_addr(map_prog2_socket),
303           __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0]))
304         : __clobber_all);
305 }
306
307 SEC("socket")
308 __description("runtime/jit: tail_call out of bounds")
309 __success __success_unpriv __retval(2)
310 __naked void tail_call_out_of_bounds(void)
311 {
312         asm volatile ("                                 \
313         r3 = 256;                                       \
314         r2 = %[map_prog1_socket] ll;                    \
315         call %[bpf_tail_call];                          \
316         r0 = 2;                                         \
317         exit;                                           \
318 "       :
319         : __imm(bpf_tail_call),
320           __imm_addr(map_prog1_socket)
321         : __clobber_all);
322 }
323
324 SEC("socket")
325 __description("runtime/jit: pass negative index to tail_call")
326 __success __success_unpriv __retval(2)
327 __naked void negative_index_to_tail_call(void)
328 {
329         asm volatile ("                                 \
330         r3 = -1;                                        \
331         r2 = %[map_prog1_socket] ll;                    \
332         call %[bpf_tail_call];                          \
333         r0 = 2;                                         \
334         exit;                                           \
335 "       :
336         : __imm(bpf_tail_call),
337           __imm_addr(map_prog1_socket)
338         : __clobber_all);
339 }
340
341 SEC("socket")
342 __description("runtime/jit: pass > 32bit index to tail_call")
343 __success __success_unpriv __retval(42)
344 /* Verifier rewrite for unpriv skips tail call here. */
345 __retval_unpriv(2)
346 __naked void _32bit_index_to_tail_call(void)
347 {
348         asm volatile ("                                 \
349         r3 = 0x100000000 ll;                            \
350         r2 = %[map_prog1_socket] ll;                    \
351         call %[bpf_tail_call];                          \
352         r0 = 2;                                         \
353         exit;                                           \
354 "       :
355         : __imm(bpf_tail_call),
356           __imm_addr(map_prog1_socket)
357         : __clobber_all);
358 }
359
360 char _license[] SEC("license") = "GPL";
This page took 0.053173 seconds and 4 git commands to generate.