1{
2	"runtime/jit: tail_call within bounds, prog once",
3	.insns = {
4	BPF_MOV64_IMM(BPF_REG_3, 0),
5	BPF_LD_MAP_FD(BPF_REG_2, 0),
6	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
7	BPF_MOV64_IMM(BPF_REG_0, 1),
8	BPF_EXIT_INSN(),
9	},
10	.fixup_prog1 = { 1 },
11	.result = ACCEPT,
12	.retval = 42,
13},
14{
15	"runtime/jit: tail_call within bounds, prog loop",
16	.insns = {
17	BPF_MOV64_IMM(BPF_REG_3, 1),
18	BPF_LD_MAP_FD(BPF_REG_2, 0),
19	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
20	BPF_MOV64_IMM(BPF_REG_0, 1),
21	BPF_EXIT_INSN(),
22	},
23	.fixup_prog1 = { 1 },
24	.result = ACCEPT,
25	.retval = 41,
26},
27{
28	"runtime/jit: tail_call within bounds, no prog",
29	.insns = {
30	BPF_MOV64_IMM(BPF_REG_3, 3),
31	BPF_LD_MAP_FD(BPF_REG_2, 0),
32	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
33	BPF_MOV64_IMM(BPF_REG_0, 1),
34	BPF_EXIT_INSN(),
35	},
36	.fixup_prog1 = { 1 },
37	.result = ACCEPT,
38	.retval = 1,
39},
40{
41	"runtime/jit: tail_call within bounds, key 2",
42	.insns = {
43	BPF_MOV64_IMM(BPF_REG_3, 2),
44	BPF_LD_MAP_FD(BPF_REG_2, 0),
45	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
46	BPF_MOV64_IMM(BPF_REG_0, 1),
47	BPF_EXIT_INSN(),
48	},
49	.fixup_prog1 = { 1 },
50	.result = ACCEPT,
51	.retval = 24,
52},
53{
54	"runtime/jit: tail_call within bounds, key 2 / key 2, first branch",
55	.insns = {
56	BPF_MOV64_IMM(BPF_REG_0, 13),
57	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
58		    offsetof(struct __sk_buff, cb[0])),
59	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
60		    offsetof(struct __sk_buff, cb[0])),
61	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
62	BPF_MOV64_IMM(BPF_REG_3, 2),
63	BPF_LD_MAP_FD(BPF_REG_2, 0),
64	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
65	BPF_MOV64_IMM(BPF_REG_3, 2),
66	BPF_LD_MAP_FD(BPF_REG_2, 0),
67	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
68	BPF_MOV64_IMM(BPF_REG_0, 1),
69	BPF_EXIT_INSN(),
70	},
71	.fixup_prog1 = { 5, 9 },
72	.result = ACCEPT,
73	.retval = 24,
74},
75{
76	"runtime/jit: tail_call within bounds, key 2 / key 2, second branch",
77	.insns = {
78	BPF_MOV64_IMM(BPF_REG_0, 14),
79	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
80		    offsetof(struct __sk_buff, cb[0])),
81	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
82		    offsetof(struct __sk_buff, cb[0])),
83	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
84	BPF_MOV64_IMM(BPF_REG_3, 2),
85	BPF_LD_MAP_FD(BPF_REG_2, 0),
86	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
87	BPF_MOV64_IMM(BPF_REG_3, 2),
88	BPF_LD_MAP_FD(BPF_REG_2, 0),
89	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
90	BPF_MOV64_IMM(BPF_REG_0, 1),
91	BPF_EXIT_INSN(),
92	},
93	.fixup_prog1 = { 5, 9 },
94	.result = ACCEPT,
95	.retval = 24,
96},
97{
98	"runtime/jit: tail_call within bounds, key 0 / key 2, first branch",
99	.insns = {
100	BPF_MOV64_IMM(BPF_REG_0, 13),
101	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
102		    offsetof(struct __sk_buff, cb[0])),
103	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
104		    offsetof(struct __sk_buff, cb[0])),
105	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
106	BPF_MOV64_IMM(BPF_REG_3, 0),
107	BPF_LD_MAP_FD(BPF_REG_2, 0),
108	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
109	BPF_MOV64_IMM(BPF_REG_3, 2),
110	BPF_LD_MAP_FD(BPF_REG_2, 0),
111	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
112	BPF_MOV64_IMM(BPF_REG_0, 1),
113	BPF_EXIT_INSN(),
114	},
115	.fixup_prog1 = { 5, 9 },
116	.result = ACCEPT,
117	.retval = 24,
118},
119{
120	"runtime/jit: tail_call within bounds, key 0 / key 2, second branch",
121	.insns = {
122	BPF_MOV64_IMM(BPF_REG_0, 14),
123	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
124		    offsetof(struct __sk_buff, cb[0])),
125	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
126		    offsetof(struct __sk_buff, cb[0])),
127	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
128	BPF_MOV64_IMM(BPF_REG_3, 0),
129	BPF_LD_MAP_FD(BPF_REG_2, 0),
130	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
131	BPF_MOV64_IMM(BPF_REG_3, 2),
132	BPF_LD_MAP_FD(BPF_REG_2, 0),
133	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
134	BPF_MOV64_IMM(BPF_REG_0, 1),
135	BPF_EXIT_INSN(),
136	},
137	.fixup_prog1 = { 5, 9 },
138	.result = ACCEPT,
139	.retval = 42,
140},
141{
142	"runtime/jit: tail_call within bounds, different maps, first branch",
143	.insns = {
144	BPF_MOV64_IMM(BPF_REG_0, 13),
145	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
146		    offsetof(struct __sk_buff, cb[0])),
147	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
148		    offsetof(struct __sk_buff, cb[0])),
149	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
150	BPF_MOV64_IMM(BPF_REG_3, 0),
151	BPF_LD_MAP_FD(BPF_REG_2, 0),
152	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
153	BPF_MOV64_IMM(BPF_REG_3, 0),
154	BPF_LD_MAP_FD(BPF_REG_2, 0),
155	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
156	BPF_MOV64_IMM(BPF_REG_0, 1),
157	BPF_EXIT_INSN(),
158	},
159	.fixup_prog1 = { 5 },
160	.fixup_prog2 = { 9 },
161	.result_unpriv = REJECT,
162	.errstr_unpriv = "tail_call abusing map_ptr",
163	.result = ACCEPT,
164	.retval = 1,
165},
166{
167	"runtime/jit: tail_call within bounds, different maps, second branch",
168	.insns = {
169	BPF_MOV64_IMM(BPF_REG_0, 14),
170	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
171		    offsetof(struct __sk_buff, cb[0])),
172	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
173		    offsetof(struct __sk_buff, cb[0])),
174	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
175	BPF_MOV64_IMM(BPF_REG_3, 0),
176	BPF_LD_MAP_FD(BPF_REG_2, 0),
177	BPF_JMP_IMM(BPF_JA, 0, 0, 3),
178	BPF_MOV64_IMM(BPF_REG_3, 0),
179	BPF_LD_MAP_FD(BPF_REG_2, 0),
180	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
181	BPF_MOV64_IMM(BPF_REG_0, 1),
182	BPF_EXIT_INSN(),
183	},
184	.fixup_prog1 = { 5 },
185	.fixup_prog2 = { 9 },
186	.result_unpriv = REJECT,
187	.errstr_unpriv = "tail_call abusing map_ptr",
188	.result = ACCEPT,
189	.retval = 42,
190},
191{
192	"runtime/jit: tail_call out of bounds",
193	.insns = {
194	BPF_MOV64_IMM(BPF_REG_3, 256),
195	BPF_LD_MAP_FD(BPF_REG_2, 0),
196	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
197	BPF_MOV64_IMM(BPF_REG_0, 2),
198	BPF_EXIT_INSN(),
199	},
200	.fixup_prog1 = { 1 },
201	.result = ACCEPT,
202	.retval = 2,
203},
204{
205	"runtime/jit: pass negative index to tail_call",
206	.insns = {
207	BPF_MOV64_IMM(BPF_REG_3, -1),
208	BPF_LD_MAP_FD(BPF_REG_2, 0),
209	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
210	BPF_MOV64_IMM(BPF_REG_0, 2),
211	BPF_EXIT_INSN(),
212	},
213	.fixup_prog1 = { 1 },
214	.result = ACCEPT,
215	.retval = 2,
216},
217{
218	"runtime/jit: pass > 32bit index to tail_call",
219	.insns = {
220	BPF_LD_IMM64(BPF_REG_3, 0x100000000ULL),
221	BPF_LD_MAP_FD(BPF_REG_2, 0),
222	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
223	BPF_MOV64_IMM(BPF_REG_0, 2),
224	BPF_EXIT_INSN(),
225	},
226	.fixup_prog1 = { 2 },
227	.result = ACCEPT,
228	.retval = 42,
229	/* Verifier rewrite for unpriv skips tail call here. */
230	.retval_unpriv = 2,
231},
232