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